Removing various reflection calls with final APIs

Change-Id: Ibf48d6015d808f86bc79ccf64e3077eb5b6ccaff
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index f4342a2..b63bbd5 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -90,7 +90,7 @@
 import com.android.launcher3.anim.AnimationLayerSet;
 import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.compat.LauncherAppsCompat;
-import com.android.launcher3.compat.PinItemRequestCompat;
+import com.android.launcher3.compat.LauncherAppsCompatVO;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
@@ -1423,8 +1423,8 @@
 
         ShortcutInfo info = null;
         if (Utilities.isAtLeastO()) {
-            info = LauncherAppsCompat.createShortcutInfoFromPinItemRequest(
-                    this, PinItemRequestCompat.getPinItemRequest(data), 0);
+            info = LauncherAppsCompatVO.createShortcutInfoFromPinItemRequest(
+                    this, LauncherAppsCompatVO.getPinItemRequest(data), 0);
         }
 
         if (info == null) {
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index 13cc7ba..c7b7782 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -23,7 +23,6 @@
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.SystemClock;
-import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -40,9 +39,7 @@
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.DragLayer.TouchCompleteListener;
 
-import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.concurrent.Executor;
 
 /**
  * {@inheritDoc}
@@ -50,8 +47,6 @@
 public class LauncherAppWidgetHostView extends AppWidgetHostView
         implements TouchCompleteListener, View.OnLongClickListener {
 
-    private static final String TAG = "LauncherWidgetHostView";
-
     // Related to the auto-advancing of widgets
     private static final long ADVANCE_INTERVAL = 20000;
     private static final long ADVANCE_STAGGER = 250;
@@ -98,13 +93,7 @@
         setBackgroundResource(R.drawable.widget_internal_focus_bg);
 
         if (Utilities.isAtLeastO()) {
-            try {
-                Method asyncMethod = AppWidgetHostView.class
-                        .getMethod("setExecutor", Executor.class);
-                asyncMethod.invoke(this, Utilities.THREAD_POOL_EXECUTOR);
-            } catch (Exception e) {
-                Log.e(TAG, "Unable to set async executor", e);
-            }
+            setExecutor(Utilities.THREAD_POOL_EXECUTOR);
         }
     }
 
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index c84a431..4813571 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3;
 
+import android.annotation.TargetApi;
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetManager;
 import android.content.ComponentName;
@@ -38,6 +39,7 @@
 import android.database.sqlite.SQLiteStatement;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -68,7 +70,6 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.reflect.Method;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -855,15 +856,16 @@
          * Removes widgets which are registered to the Launcher's host, but are not present
          * in our model.
          */
+        @TargetApi(Build.VERSION_CODES.O)
         public void removeGhostWidgets(SQLiteDatabase db) {
             // Get all existing widget ids.
             final AppWidgetHost host = newLauncherWidgetHost();
             final int[] allWidgets;
             try {
-                Method getter = AppWidgetHost.class.getDeclaredMethod("getAppWidgetIds");
-                getter.setAccessible(true);
-                allWidgets = (int[]) getter.invoke(host);
-            } catch (Exception e) {
+                // Although the method was defined in O, it has existed since the beginning of time,
+                // so it might work on older platforms as well.
+                allWidgets = host.getAppWidgetIds();
+            } catch (IncompatibleClassChangeError e) {
                 Log.e(TAG, "getAppWidgetIds not supported", e);
                 return;
             }
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index 472cfc9..26f4ae7 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -26,13 +26,8 @@
 import android.os.UserHandle;
 import android.support.annotation.Nullable;
 
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.ShortcutInfo;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.graphics.LauncherIcons;
 import com.android.launcher3.shortcuts.ShortcutInfoCompat;
-import com.android.launcher3.util.LooperExecutor;
 import com.android.launcher3.util.PackageUserKey;
 
 import java.util.List;
@@ -88,62 +83,6 @@
     public abstract List<ShortcutConfigActivityInfo> getCustomShortcutActivityList(
             @Nullable PackageUserKey packageUser);
 
-    /**
-     * request.accept() will initiate the following flow:
-     *      -> go-to-system-process for actual processing (a)
-     *      -> callback-to-launcher on UI thread (b)
-     *      -> post callback on the worker thread (c)
-     *      -> Update model and unpin (in system) any shortcut not in out model. (d)
-     *
-     * Note that (b) will take at-least one frame as it involves posting callback from binder
-     * thread to UI thread.
-     * If (d) happens before we add this shortcut to our model, we will end up unpinning
-     * the shortcut in the system.
-     * Here its the caller's responsibility to add the newly created ShortcutInfo immediately
-     * to the model (which may involves a single post-to-worker-thread). That will guarantee
-     * that (d) happens after model is updated.
-     */
-    @Nullable
-    public static ShortcutInfo createShortcutInfoFromPinItemRequest(
-            Context context, final PinItemRequestCompat request, final long acceptDelay) {
-        if (request != null &&
-                request.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT &&
-                request.isValid()) {
-
-            if (acceptDelay <= 0) {
-                if (!request.accept()) {
-                    return null;
-                }
-            } else {
-                // Block the worker thread until the accept() is called.
-                new LooperExecutor(LauncherModel.getWorkerLooper()).execute(new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            Thread.sleep(acceptDelay);
-                        } catch (InterruptedException e) {
-                            // Ignore
-                        }
-                        if (request.isValid()) {
-                            request.accept();
-                        }
-                    }
-                });
-            }
-
-            ShortcutInfoCompat compat = new ShortcutInfoCompat(request.getShortcutInfo());
-            ShortcutInfo info = new ShortcutInfo(compat, context);
-            // Apply the unbadged icon and fetch the actual icon asynchronously.
-            info.iconBitmap = LauncherIcons
-                    .createShortcutIcon(compat, context, false /* badged */);
-            LauncherAppState.getInstance(context).getModel()
-                    .updateAndBindShortcutInfo(info, compat);
-            return info;
-        } else {
-            return null;
-        }
-    }
-
     public void showAppDetailsForProfile(ComponentName component, UserHandle user) {
         showAppDetailsForProfile(component, user, null, null);
     }
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVO.java b/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
index d145539..3214b46 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
@@ -18,20 +18,27 @@
 
 import android.annotation.TargetApi;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.PinItemRequest;
 import android.content.pm.PackageManager;
 import android.os.Build;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.UserHandle;
 import android.support.annotation.Nullable;
-import android.util.Log;
 
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.ShortcutInfo;
 import com.android.launcher3.compat.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVO;
+import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.shortcuts.ShortcutInfoCompat;
+import com.android.launcher3.util.LooperExecutor;
 import com.android.launcher3.util.PackageUserKey;
 
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -45,11 +52,6 @@
     @Override
     public ApplicationInfo getApplicationInfo(String packageName, int flags, UserHandle user) {
         try {
-            // TODO: Temporary workaround until the API signature is updated
-            if (false) {
-                throw new PackageManager.NameNotFoundException();
-            }
-
             ApplicationInfo info = mLauncherApps.getApplicationInfo(packageName, flags, user);
             return (info.flags & ApplicationInfo.FLAG_INSTALLED) == 0 || !info.enabled
                     ? null : info;
@@ -64,34 +66,89 @@
         List<ShortcutConfigActivityInfo> result = new ArrayList<>();
         UserHandle myUser = Process.myUserHandle();
 
-        try {
-            Method m = LauncherApps.class.getDeclaredMethod("getShortcutConfigActivityList",
-                    String.class, UserHandle.class);
-            final List<UserHandle> users;
-            final String packageName;
-            if (packageUser == null) {
-                users = UserManagerCompat.getInstance(mContext).getUserProfiles();
-                packageName = null;
-            } else {
-                users = new ArrayList<>(1);
-                users.add(packageUser.mUser);
-                packageName = packageUser.mPackageName;
-            }
-            for (UserHandle user : users) {
-                boolean ignoreTargetSdk = myUser.equals(user);
-                List<LauncherActivityInfo> activities =
-                        (List<LauncherActivityInfo>) m.invoke(mLauncherApps, packageName, user);
-                for (LauncherActivityInfo activityInfo : activities) {
-                    if (ignoreTargetSdk || activityInfo.getApplicationInfo().targetSdkVersion >=
-                            Build.VERSION_CODES.O) {
-                        result.add(new ShortcutConfigActivityInfoVO(activityInfo));
-                    }
+        final List<UserHandle> users;
+        final String packageName;
+        if (packageUser == null) {
+            users = UserManagerCompat.getInstance(mContext).getUserProfiles();
+            packageName = null;
+        } else {
+            users = new ArrayList<>(1);
+            users.add(packageUser.mUser);
+            packageName = packageUser.mPackageName;
+        }
+        for (UserHandle user : users) {
+            boolean ignoreTargetSdk = myUser.equals(user);
+            List<LauncherActivityInfo> activities =
+                    mLauncherApps.getShortcutConfigActivityList(packageName, user);
+            for (LauncherActivityInfo activityInfo : activities) {
+                if (ignoreTargetSdk || activityInfo.getApplicationInfo().targetSdkVersion >=
+                        Build.VERSION_CODES.O) {
+                    result.add(new ShortcutConfigActivityInfoVO(activityInfo));
                 }
             }
-        } catch (Exception e) {
-            Log.e("LauncherAppsCompatVO", "Error calling new API", e);
         }
 
         return result;
     }
+
+    /**
+     * request.accept() will initiate the following flow:
+     *      -> go-to-system-process for actual processing (a)
+     *      -> callback-to-launcher on UI thread (b)
+     *      -> post callback on the worker thread (c)
+     *      -> Update model and unpin (in system) any shortcut not in out model. (d)
+     *
+     * Note that (b) will take at-least one frame as it involves posting callback from binder
+     * thread to UI thread.
+     * If (d) happens before we add this shortcut to our model, we will end up unpinning
+     * the shortcut in the system.
+     * Here its the caller's responsibility to add the newly created ShortcutInfo immediately
+     * to the model (which may involves a single post-to-worker-thread). That will guarantee
+     * that (d) happens after model is updated.
+     */
+    @Nullable
+    public static ShortcutInfo createShortcutInfoFromPinItemRequest(
+            Context context, final PinItemRequest request, final long acceptDelay) {
+        if (request != null &&
+                request.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT &&
+                request.isValid()) {
+
+            if (acceptDelay <= 0) {
+                if (!request.accept()) {
+                    return null;
+                }
+            } else {
+                // Block the worker thread until the accept() is called.
+                new LooperExecutor(LauncherModel.getWorkerLooper()).execute(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            Thread.sleep(acceptDelay);
+                        } catch (InterruptedException e) {
+                            // Ignore
+                        }
+                        if (request.isValid()) {
+                            request.accept();
+                        }
+                    }
+                });
+            }
+
+            ShortcutInfoCompat compat = new ShortcutInfoCompat(request.getShortcutInfo());
+            ShortcutInfo info = new ShortcutInfo(compat, context);
+            // Apply the unbadged icon and fetch the actual icon asynchronously.
+            info.iconBitmap = LauncherIcons
+                    .createShortcutIcon(compat, context, false /* badged */);
+            LauncherAppState.getInstance(context).getModel()
+                    .updateAndBindShortcutInfo(info, compat);
+            return info;
+        } else {
+            return null;
+        }
+    }
+
+    public static PinItemRequest getPinItemRequest(Intent intent) {
+        Parcelable extra = intent.getParcelableExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST);
+        return extra instanceof PinItemRequest ? (PinItemRequest) extra : null;
+    }
 }
diff --git a/src/com/android/launcher3/compat/PinItemRequestCompat.java b/src/com/android/launcher3/compat/PinItemRequestCompat.java
deleted file mode 100644
index 1308cba..0000000
--- a/src/com/android/launcher3/compat/PinItemRequestCompat.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.compat;
-
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ShortcutInfo;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.launcher3.Utilities;
-
-/**
- * A wrapper around platform implementation of PinItemRequestCompat until the
- * updated SDK is available.
- */
-public class PinItemRequestCompat implements Parcelable {
-
-    public static final String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
-
-    public static final int REQUEST_TYPE_SHORTCUT = 1;
-    public static final int REQUEST_TYPE_APPWIDGET = 2;
-
-    private final Parcelable mObject;
-
-    private PinItemRequestCompat(Parcelable object) {
-        mObject = object;
-    }
-
-    public int getRequestType() {
-        return (Integer) invokeMethod("getRequestType");
-    }
-
-    public ShortcutInfo getShortcutInfo() {
-        return (ShortcutInfo) invokeMethod("getShortcutInfo");
-    }
-
-    public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
-        try {
-            return (AppWidgetProviderInfo) mObject.getClass()
-                    .getDeclaredMethod("getAppWidgetProviderInfo", Context.class)
-                    .invoke(mObject, context);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public boolean isValid() {
-        return (Boolean) invokeMethod("isValid");
-    }
-
-    public boolean accept() {
-        return (Boolean) invokeMethod("accept");
-    }
-
-    public boolean accept(Bundle options) {
-        try {
-            return (Boolean) mObject.getClass().getDeclaredMethod("accept", Bundle.class)
-                    .invoke(mObject, options);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public Bundle getExtras() {
-        try {
-            return (Bundle) mObject.getClass().getDeclaredMethod("getExtras").invoke(mObject);
-        } catch (Exception e) {
-            return null;
-        }
-    }
-
-    private Object invokeMethod(String methodName) {
-        try {
-            return mObject.getClass().getDeclaredMethod(methodName).invoke(mObject);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int i) {
-        parcel.writeParcelable(mObject, i);
-    }
-
-    public static final Parcelable.Creator<PinItemRequestCompat> CREATOR =
-            new Parcelable.Creator<PinItemRequestCompat>() {
-                public PinItemRequestCompat createFromParcel(Parcel source) {
-                    Parcelable object = source.readParcelable(null);
-                    return new PinItemRequestCompat(object);
-                }
-
-                public PinItemRequestCompat[] newArray(int size) {
-                    return new PinItemRequestCompat[size];
-                }
-            };
-
-    public static PinItemRequestCompat getPinItemRequest(Intent intent) {
-        if (!Utilities.isAtLeastO()) {
-            return null;
-        }
-        Parcelable extra = intent.getParcelableExtra(EXTRA_PIN_ITEM_REQUEST);
-        return extra == null ? null : new PinItemRequestCompat(extra);
-    }
-}
diff --git a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
index 4a55e8c..6bdc627 100644
--- a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
@@ -37,8 +37,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.ShortcutInfo;
 
-import java.lang.reflect.Method;
-
 /**
  * Wrapper class for representing a shortcut configure activity.
  */
@@ -151,15 +149,13 @@
             if (getUser().equals(Process.myUserHandle())) {
                 return super.startConfigActivity(activity, requestCode);
             }
+            IntentSender is = activity.getSystemService(LauncherApps.class)
+                    .getShortcutConfigActivityIntent(mInfo);
             try {
-                Method m = LauncherApps.class.getDeclaredMethod(
-                        "getShortcutConfigActivityIntent", LauncherActivityInfo.class);
-                IntentSender is = (IntentSender) m.invoke(
-                        activity.getSystemService(LauncherApps.class), mInfo);
                 activity.startIntentSenderForResult(is, requestCode, null, 0, 0, 0);
                 return true;
-            } catch (Exception e) {
-                Log.e(TAG, "Error calling new API", e);
+            } catch (IntentSender.SendIntentException e) {
+                Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
                 return false;
             }
         }
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 09592a8..29789c8 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -28,6 +28,7 @@
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.Intent;
+import android.content.pm.LauncherApps.PinItemRequest;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Point;
@@ -50,7 +51,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.compat.AppWidgetManagerCompat;
-import com.android.launcher3.compat.PinItemRequestCompat;
+import com.android.launcher3.compat.LauncherAppsCompatVO;
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.shortcuts.ShortcutInfoCompat;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
@@ -60,7 +61,7 @@
 import com.android.launcher3.widget.WidgetHostViewLoader;
 import com.android.launcher3.widget.WidgetImageView;
 
-@TargetApi(Build.VERSION_CODES.N_MR1)
+@TargetApi(Build.VERSION_CODES.O)
 public class AddItemActivity extends BaseActivity implements OnLongClickListener, OnTouchListener {
 
     private static final int SHADOW_SIZE = 10;
@@ -70,7 +71,7 @@
 
     private final PointF mLastTouchPos = new PointF();
 
-    private PinItemRequestCompat mRequest;
+    private PinItemRequest mRequest;
     private LauncherAppState mApp;
     private InvariantDeviceProfile mIdp;
 
@@ -87,7 +88,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mRequest = PinItemRequestCompat.getPinItemRequest(getIntent());
+        mRequest = LauncherAppsCompatVO.getPinItemRequest(getIntent());
         if (mRequest == null) {
             finish();
             return;
@@ -101,9 +102,9 @@
         mDeviceProfile = mIdp.getDeviceProfile(getApplicationContext());
 
         setContentView(R.layout.add_item_confirmation_activity);
-        mWidgetCell = (LivePreviewWidgetCell) findViewById(R.id.widget_cell);
+        mWidgetCell = findViewById(R.id.widget_cell);
 
-        if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) {
+        if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
             setupShortcut();
         } else {
             if (!setupWidget()) {
@@ -226,7 +227,7 @@
      * Called when place-automatically button is clicked.
      */
     public void onPlaceAutomaticallyClick(View v) {
-        if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) {
+        if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
             InstallShortcutReceiver.queueShortcut(
                     new ShortcutInfoCompat(mRequest.getShortcutInfo()), this);
             logCommand(Action.Command.CONFIRM);
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index df0c47c..f9f4e50 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -16,11 +16,14 @@
 
 package com.android.launcher3.dragndrop;
 
+import android.annotation.TargetApi;
 import android.appwidget.AppWidgetManager;
 import android.content.ClipDescription;
 import android.content.Intent;
+import android.content.pm.LauncherApps.PinItemRequest;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -40,7 +43,7 @@
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.PendingAddItemInfo;
 import com.android.launcher3.R;
-import com.android.launcher3.compat.PinItemRequestCompat;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -55,6 +58,7 @@
  * {@link DragSource} for handling drop from a different window. This object is initialized
  * in the source window and is passed on to the Launcher activity as an Intent extra.
  */
+@TargetApi(Build.VERSION_CODES.O)
 public class PinItemDragListener
         implements Parcelable, View.OnDragListener, DragSource, DragOptions.PreDragCondition {
 
@@ -63,7 +67,7 @@
     private static final String MIME_TYPE_PREFIX = "com.android.launcher3.drag_and_drop/";
     public static final String EXTRA_PIN_ITEM_DRAG_LISTENER = "pin_item_drag_listener";
 
-    private final PinItemRequestCompat mRequest;
+    private final PinItemRequest mRequest;
 
     // Position of preview relative to the touch location
     private final Rect mPreviewRect;
@@ -78,7 +82,7 @@
     private DragController mDragController;
     private long mDragStartTime;
 
-    public PinItemDragListener(PinItemRequestCompat request, Rect previewRect,
+    public PinItemDragListener(PinItemRequest request, Rect previewRect,
             int previewBitmapWidth, int previewViewWidth) {
         mRequest = request;
         mPreviewRect = previewRect;
@@ -88,7 +92,7 @@
     }
 
     private PinItemDragListener(Parcel parcel) {
-        mRequest = PinItemRequestCompat.CREATOR.createFromParcel(parcel);
+        mRequest = PinItemRequest.CREATOR.createFromParcel(parcel);
         mPreviewRect = Rect.CREATOR.createFromParcel(parcel);
         mPreviewBitmapWidth = parcel.readInt();
         mPreviewViewWidth = parcel.readInt();
@@ -146,7 +150,7 @@
         }
 
         final PendingAddItemInfo item;
-        if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) {
+        if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
             item = new PendingAddShortcutInfo(
                     new PinShortcutRequestActivityInfo(mRequest, mLauncher));
         } else {
@@ -177,7 +181,7 @@
         // across windows, using drag position here give a good estimate for relative position
         // to source window.
         PendingItemDragHelper dragHelper = new PendingItemDragHelper(view);
-        if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_APPWIDGET) {
+        if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_APPWIDGET) {
             dragHelper.setPreview(getPreview(mRequest));
         }
 
@@ -271,7 +275,7 @@
         }
     }
 
-    public static RemoteViews getPreview(PinItemRequestCompat request) {
+    public static RemoteViews getPreview(PinItemRequest request) {
         Bundle extras = request.getExtras();
         if (extras != null &&
                 extras.get(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW) instanceof RemoteViews) {
@@ -281,6 +285,9 @@
     }
 
     public static boolean handleDragRequest(Launcher launcher, Intent intent) {
+        if (!Utilities.isAtLeastO()) {
+            return false;
+        }
         if (intent == null || !Intent.ACTION_MAIN.equals(intent.getAction())) {
             return false;
         }
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index bb5ac5b..52abbc7 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -21,6 +21,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.PinItemRequest;
 import android.content.pm.ShortcutInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
@@ -30,26 +31,25 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.R;
-import com.android.launcher3.compat.LauncherAppsCompat;
-import com.android.launcher3.compat.PinItemRequestCompat;
+import com.android.launcher3.compat.LauncherAppsCompatVO;
 import com.android.launcher3.compat.ShortcutConfigActivityInfo;
 
 /**
  * Extension of ShortcutConfigActivityInfo to be used in the confirmation prompt for pin item
  * request.
  */
-@TargetApi(Build.VERSION_CODES.N_MR1)
+@TargetApi(Build.VERSION_CODES.O)
 class PinShortcutRequestActivityInfo extends ShortcutConfigActivityInfo {
 
     // Class name used in the target component, such that it will never represent an
     // actual existing class.
     private static final String DUMMY_COMPONENT_CLASS = "pinned-shortcut";
 
-    private final PinItemRequestCompat mRequest;
+    private final PinItemRequest mRequest;
     private final ShortcutInfo mInfo;
     private final Context mContext;
 
-    public PinShortcutRequestActivityInfo(PinItemRequestCompat request, Context context) {
+    public PinShortcutRequestActivityInfo(PinItemRequest request, Context context) {
         super(new ComponentName(request.getShortcutInfo().getPackage(), DUMMY_COMPONENT_CLASS),
                 request.getShortcutInfo().getUserHandle());
         mRequest = request;
@@ -80,7 +80,7 @@
                 Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT +
                 mContext.getResources().getInteger(R.integer.config_overlayTransitionTime) / 2;
         // Delay the actual accept() call until the drop animation is complete.
-        return LauncherAppsCompat.createShortcutInfoFromPinItemRequest(
+        return LauncherAppsCompatVO.createShortcutInfoFromPinItemRequest(
                 mContext, mRequest, duration);
     }
 
diff --git a/src/com/android/launcher3/dragndrop/PinWidgetFlowHandler.java b/src/com/android/launcher3/dragndrop/PinWidgetFlowHandler.java
index b6da6ad..9f617e4 100644
--- a/src/com/android/launcher3/dragndrop/PinWidgetFlowHandler.java
+++ b/src/com/android/launcher3/dragndrop/PinWidgetFlowHandler.java
@@ -16,15 +16,17 @@
 
 package com.android.launcher3.dragndrop;
 
+import android.annotation.TargetApi;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
+import android.content.pm.LauncherApps.PinItemRequest;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.compat.PinItemRequestCompat;
 import com.android.launcher3.widget.WidgetAddFlowHandler;
 
 /**
@@ -33,18 +35,19 @@
  * No config activity is shown even if it is defined in widget config. And a callback is sent when
  * the widget is bound.
  */
+@TargetApi(Build.VERSION_CODES.O)
 public class PinWidgetFlowHandler extends WidgetAddFlowHandler implements Parcelable {
 
-    private final PinItemRequestCompat mRequest;
+    private final PinItemRequest mRequest;
 
-    public PinWidgetFlowHandler(AppWidgetProviderInfo providerInfo, PinItemRequestCompat request) {
+    public PinWidgetFlowHandler(AppWidgetProviderInfo providerInfo, PinItemRequest request) {
         super(providerInfo);
         mRequest = request;
     }
 
     protected PinWidgetFlowHandler(Parcel parcel) {
         super(parcel);
-        mRequest = PinItemRequestCompat.CREATOR.createFromParcel(parcel);
+        mRequest = PinItemRequest.CREATOR.createFromParcel(parcel);
     }
 
     @Override