Merge "Fix crash when primary user select app installed by secondary user." into oc-dev
diff --git a/src/com/android/settings/applications/AppCounter.java b/src/com/android/settings/applications/AppCounter.java
index 8758b14..8eff526 100644
--- a/src/com/android/settings/applications/AppCounter.java
+++ b/src/com/android/settings/applications/AppCounter.java
@@ -32,7 +32,7 @@
 
     public AppCounter(Context context, PackageManagerWrapper packageManager) {
         mPm = packageManager;
-        mUm = UserManager.get(context);
+        mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
     }
 
     @Override
diff --git a/src/com/android/settings/applications/AppStateAppOpsBridge.java b/src/com/android/settings/applications/AppStateAppOpsBridge.java
index cfbb2fc..420d955 100644
--- a/src/com/android/settings/applications/AppStateAppOpsBridge.java
+++ b/src/com/android/settings/applications/AppStateAppOpsBridge.java
@@ -19,12 +19,12 @@
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.PackageOps;
 import android.content.Context;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.SparseArray;
@@ -46,7 +46,7 @@
 
     private static final String TAG = "AppStateAppOpsBridge";
 
-    private final IPackageManager mIPackageManager;
+    private final IPackageManagerWrapper mIPackageManager;
     private final UserManager mUserManager;
     private final List<UserHandle> mProfiles;
     private final AppOpsManager mAppOpsManager;
@@ -56,9 +56,16 @@
 
     public AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback,
             int appOpsOpCode, String[] permissions) {
+        this(context, appState, callback, appOpsOpCode, permissions,
+            new IPackageManagerWrapperImpl(AppGlobals.getPackageManager()));
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+    AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback,
+            int appOpsOpCode, String[] permissions, IPackageManagerWrapper packageManager) {
         super(appState, callback);
         mContext = context;
-        mIPackageManager = AppGlobals.getPackageManager();
+        mIPackageManager = packageManager;
         mUserManager = UserManager.get(context);
         mProfiles = mUserManager.getUserProfiles();
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
@@ -92,18 +99,21 @@
                 .getUserId(uid)));
         try {
             permissionState.packageInfo = mIPackageManager.getPackageInfo(pkg,
-                    PackageManager.GET_PERMISSIONS | PackageManager.MATCH_UNINSTALLED_PACKAGES,
+                    PackageManager.GET_PERMISSIONS | PackageManager.MATCH_ANY_USER,
                     permissionState.userHandle.getIdentifier());
-            // Check static permission state (whatever that is declared in package manifest)
-            String[] requestedPermissions = permissionState.packageInfo.requestedPermissions;
-            int[] permissionFlags = permissionState.packageInfo.requestedPermissionsFlags;
-            if (requestedPermissions != null) {
-                for (int i = 0; i < requestedPermissions.length; i++) {
-                    if (doesAnyPermissionMatch(requestedPermissions[i], mPermissions)) {
-                        permissionState.permissionDeclared = true;
-                        if ((permissionFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
-                            permissionState.staticPermissionGranted = true;
-                            break;
+            if (permissionState.packageInfo != null) {
+                // Check static permission state (whatever that is declared in package manifest)
+                String[] requestedPermissions = permissionState.packageInfo.requestedPermissions;
+                int[] permissionFlags = permissionState.packageInfo.requestedPermissionsFlags;
+                if (requestedPermissions != null) {
+                    for (int i = 0; i < requestedPermissions.length; i++) {
+                        if (doesAnyPermissionMatch(requestedPermissions[i], mPermissions)) {
+                            permissionState.permissionDeclared = true;
+                            if ((permissionFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED)
+                                    != 0) {
+                                permissionState.staticPermissionGranted = true;
+                                break;
+                            }
                         }
                     }
                 }
diff --git a/src/com/android/settings/applications/IPackageManagerWrapper.java b/src/com/android/settings/applications/IPackageManagerWrapper.java
index f885985..b4d1b85 100644
--- a/src/com/android/settings/applications/IPackageManagerWrapper.java
+++ b/src/com/android/settings/applications/IPackageManagerWrapper.java
@@ -17,6 +17,8 @@
 package com.android.settings.applications;
 
 import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.os.RemoteException;
 
@@ -41,4 +43,33 @@
      * @see android.content.pm.IPackageManager#findPersistentPreferredActivity
      */
     ResolveInfo findPersistentPreferredActivity(Intent intent, int userId) throws RemoteException;
+
+    /**
+     * Calls {@code IPackageManager.getPackageInfo()}.
+     *
+     * @see android.content.pm.IPackageManager#getPackageInfo
+     */
+    PackageInfo getPackageInfo(String packageName, int flags, int userId) throws RemoteException;
+
+    /**
+     * Calls {@code IPackageManager.getAppOpPermissionPackages()}.
+     *
+     * @see android.content.pm.IPackageManager#getAppOpPermissionPackages
+     */
+    String[] getAppOpPermissionPackages(String permissionName) throws RemoteException;
+
+    /**
+     * Calls {@code IPackageManager.isPackageAvailable()}.
+     *
+     * @see android.content.pm.IPackageManager#isPackageAvailable
+     */
+    boolean isPackageAvailable(String packageName, int userId) throws RemoteException;
+
+    /**
+     * Calls {@code IPackageManager.getPackagesHoldingPermissions()}.
+     *
+     * @see android.content.pm.IPackageManager#getPackagesHoldingPermissions
+     */
+    ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
+        String[] permissions, int flags, int userId) throws RemoteException;
 }
diff --git a/src/com/android/settings/applications/IPackageManagerWrapperImpl.java b/src/com/android/settings/applications/IPackageManagerWrapperImpl.java
index 5ea15b9..af5f378 100644
--- a/src/com/android/settings/applications/IPackageManagerWrapperImpl.java
+++ b/src/com/android/settings/applications/IPackageManagerWrapperImpl.java
@@ -18,6 +18,8 @@
 
 import android.content.Intent;
 import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.os.RemoteException;
 
@@ -39,4 +41,27 @@
             throws RemoteException {
         return mPms.findPersistentPreferredActivity(intent, userId);
     }
+
+    @Override
+    public PackageInfo getPackageInfo(String packageName, int flags, int userId)
+            throws RemoteException {
+        return mPms.getPackageInfo(packageName, flags, userId);
+    }
+
+    @Override
+    public String[] getAppOpPermissionPackages(String permissionName) throws RemoteException {
+        return mPms.getAppOpPermissionPackages(permissionName);
+    }
+
+    @Override
+    public boolean isPackageAvailable(String packageName, int userId) throws RemoteException {
+        return mPms.isPackageAvailable(packageName, userId);
+    }
+
+    @Override
+    public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
+        String[] permissions, int flags, int userId) throws RemoteException {
+        return mPms.getPackagesHoldingPermissions(permissions, flags, userId);
+    }
+
 }
diff --git a/src/com/android/settings/applications/RunningState.java b/src/com/android/settings/applications/RunningState.java
index dd44887..d4abe6c 100644
--- a/src/com/android/settings/applications/RunningState.java
+++ b/src/com/android/settings/applications/RunningState.java
@@ -500,7 +500,7 @@
                 si.mRunningService = service;
                 try {
                     si.mServiceInfo = ActivityThread.getPackageManager().getServiceInfo(
-                            service.service, PackageManager.MATCH_UNINSTALLED_PACKAGES,
+                            service.service, PackageManager.MATCH_ANY_USER,
                             UserHandle.getUserId(service.uid));
 
                     if (si.mServiceInfo == null) {
diff --git a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
index 6c23b39..69f174b 100644
--- a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
+++ b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
@@ -144,7 +144,7 @@
             } catch (Exception e) {
             }
             try {
-                pm.getPackageInfo(value, PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                pm.getPackageInfo(value, PackageManager.MATCH_ANY_USER);
                 logPackageName(key, value);
             } catch (PackageManager.NameNotFoundException e) {
                 // Clearly not a package, and it's unlikely this preference is in prefSet, so
diff --git a/tests/robotests/src/com/android/settings/applications/AppStateAppOpsBridgeTest.java b/tests/robotests/src/com/android/settings/applications/AppStateAppOpsBridgeTest.java
new file mode 100644
index 0000000..f17509a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/AppStateAppOpsBridgeTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.settings.applications;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
+import android.Manifest;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.UserManager;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public final class AppStateAppOpsBridgeTest {
+
+    @Mock private Context mContext;
+    @Mock private UserManager mUserManager;
+    @Mock private IPackageManagerWrapper mPackageManagerService;
+    @Mock private AppOpsManager mAppOpsManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
+    }
+
+    @Test
+    public void getPermissionInfo_nullPackageInfo_shouldNotCrash() throws RemoteException {
+        when(mPackageManagerService.getPackageInfo(anyString(), anyInt(), anyInt()))
+            .thenReturn(null);
+        TestAppStateAppOpsBridge appStateAppOpsBridge = new TestAppStateAppOpsBridge();
+
+        appStateAppOpsBridge.getPermissionInfo("pkg1", 1);
+        // should not crash
+    }
+
+    private class TestAppStateAppOpsBridge extends AppStateAppOpsBridge {
+        public TestAppStateAppOpsBridge() {
+            super(mContext, null, null, AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+                new String[] {Manifest.permission.SYSTEM_ALERT_WINDOW},
+                mPackageManagerService);
+        }
+
+        @Override
+        protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
+        }
+    }
+}