summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/packageinstaller/PackageInstallerActivity.java274
-rwxr-xr-xsrc/com/android/packageinstaller/UninstallAppProgress.java14
-rwxr-xr-xsrc/com/android/packageinstaller/UninstallerActivity.java20
-rw-r--r--src/com/android/packageinstaller/permission/model/AppPermissionGroup.java23
-rw-r--r--src/com/android/packageinstaller/permission/model/AppPermissions.java26
-rw-r--r--src/com/android/packageinstaller/permission/model/PermissionApps.java2
-rw-r--r--src/com/android/packageinstaller/permission/model/PermissionGroups.java2
-rw-r--r--src/com/android/packageinstaller/permission/model/PermissionStatusReceiver.java2
-rw-r--r--src/com/android/packageinstaller/permission/ui/ReviewPermissionsActivity.java56
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java2
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java3
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java2
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java6
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java17
-rw-r--r--src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java1
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java2
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java3
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java2
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java3
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java1
-rw-r--r--src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java1
-rw-r--r--src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java21
-rw-r--r--src/com/android/packageinstaller/permission/ui/wear/TitledSettingsFragment.java21
-rw-r--r--src/com/android/packageinstaller/util/Utils.java (renamed from src/com/android/packageinstaller/permission/utils/Utils.java)4
-rw-r--r--src/com/android/packageinstaller/wear/WearPackageArgs.java14
-rw-r--r--src/com/android/packageinstaller/wear/WearPackageInstallerService.java61
-rw-r--r--src/com/android/packageinstaller/wear/WearPackageUtil.java13
27 files changed, 404 insertions, 192 deletions
diff --git a/src/com/android/packageinstaller/PackageInstallerActivity.java b/src/com/android/packageinstaller/PackageInstallerActivity.java
index 79500e6e..9681d2cd 100644
--- a/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -33,7 +33,9 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.VerificationParams;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.UserManager;
@@ -46,10 +48,16 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AppSecurityPermissions;
import android.widget.Button;
+import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TextView;
+import com.android.packageinstaller.util.Utils;
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
/*
* This activity is launched when a new application is installed via side loading
@@ -65,12 +73,20 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
private static final String TAG = "PackageInstaller";
private static final int REQUEST_ENABLE_UNKNOWN_SOURCES = 1;
+ private static final int REQUEST_INSTALL_PACKAGE = 2;
+
+ private static final String SCHEME_FILE = "file";
+ private static final String SCHEME_CONTENT = "content";
+ private static final String SCHEME_PACKAGE = "package";
private int mSessionId = -1;
private Uri mPackageURI;
private Uri mOriginatingURI;
private Uri mReferrerURI;
private int mOriginatingUid = VerificationParams.NO_UID;
+ private File mContentUriApkStagingFile;
+
+ private AsyncTask<Uri, Void, File> mStagingAsynTask;
private boolean localLOGV = false;
PackageManager mPm;
@@ -108,6 +124,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
private void startInstallConfirm() {
TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost);
tabHost.setup();
+ tabHost.setVisibility(View.VISIBLE);
ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
TabsAdapter adapter = new TabsAdapter(this, tabHost, viewPager);
// If the app supports runtime permissions the new permissions will
@@ -183,10 +200,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
((TextView)findViewById(R.id.install_confirm_question)).setText(msg);
}
mInstallConfirm.setVisibility(View.VISIBLE);
- mOk = (Button)findViewById(R.id.ok_button);
- mCancel = (Button)findViewById(R.id.cancel_button);
- mOk.setOnClickListener(this);
- mCancel.setOnClickListener(this);
+ mOk.setEnabled(true);
if (mScrollView == null) {
// There is nothing to scroll view, so the ok button is immediately
// set to install.
@@ -320,14 +334,14 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
setResult(RESULT_OK);
- finish();
+ clearCachedApkIfNeededAndFinish();
}
})
.setOnCancelListener(this)
.create();
}
return null;
- }
+ }
private void launchSecuritySettings() {
Intent launchSettingsIntent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
@@ -341,9 +355,8 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
// implement a "allow untrusted source once" feature.
if (request == REQUEST_ENABLE_UNKNOWN_SOURCES && result == RESULT_OK) {
initiateInstall();
- } else {
- finish();
}
+ clearCachedApkIfNeededAndFinish();
}
private boolean isInstallRequestFromUnknownSource(Intent intent) {
@@ -430,6 +443,10 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
final Intent intent = getIntent();
+ mOriginatingUid = getOriginatingUid(intent);
+
+ final Uri packageUri;
+
if (PackageInstaller.ACTION_CONFIRM_PERMISSIONS.equals(intent.getAction())) {
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1);
final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(sessionId);
@@ -440,72 +457,37 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
}
mSessionId = sessionId;
- mPackageURI = Uri.fromFile(new File(info.resolvedBaseCodePath));
+ packageUri = Uri.fromFile(new File(info.resolvedBaseCodePath));
mOriginatingURI = null;
mReferrerURI = null;
} else {
mSessionId = -1;
- mPackageURI = intent.getData();
+ packageUri = intent.getData();
mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
}
- final boolean unknownSourcesAllowedByAdmin = isUnknownSourcesAllowedByAdmin();
- final boolean unknownSourcesAllowedByUser = isUnknownSourcesEnabled();
-
- if (DeviceUtils.isWear(this)) {
- showDialogInner(DLG_NOT_SUPPORTED_ON_WEAR);
- return;
- }
-
- final String scheme = mPackageURI.getScheme();
- if (scheme != null && !"file".equals(scheme) && !"package".equals(scheme)) {
- Log.w(TAG, "Unsupported scheme " + scheme);
+ // if there's nothing to do, quietly slip into the ether
+ if (packageUri == null) {
+ Log.w(TAG, "Unspecified source");
setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
finish();
return;
}
- final PackageUtil.AppSnippet as;
- if ("package".equals(mPackageURI.getScheme())) {
- try {
- mPkgInfo = mPm.getPackageInfo(mPackageURI.getSchemeSpecificPart(),
- PackageManager.GET_PERMISSIONS | PackageManager.GET_UNINSTALLED_PACKAGES);
- } catch (NameNotFoundException e) {
- }
- if (mPkgInfo == null) {
- Log.w(TAG, "Requested package " + mPackageURI.getScheme()
- + " not available. Discontinuing installation");
- showDialogInner(DLG_PACKAGE_ERROR);
- setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
- return;
- }
- as = new PackageUtil.AppSnippet(mPm.getApplicationLabel(mPkgInfo.applicationInfo),
- mPm.getApplicationIcon(mPkgInfo.applicationInfo));
- } else {
- final File sourceFile = new File(mPackageURI.getPath());
- PackageParser.Package parsed = PackageUtil.getPackageInfo(sourceFile);
-
- // Check for parse errors
- if (parsed == null) {
- Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
- showDialogInner(DLG_PACKAGE_ERROR);
- setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
- return;
- }
- mPkgInfo = PackageParser.generatePackageInfo(parsed, null,
- PackageManager.GET_PERMISSIONS, 0, 0, null,
- new PackageUserState());
- as = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
+ if (DeviceUtils.isWear(this)) {
+ showDialogInner(DLG_NOT_SUPPORTED_ON_WEAR);
+ return;
}
//set view
setContentView(R.layout.install_start);
mInstallConfirm = findViewById(R.id.install_confirm_panel);
mInstallConfirm.setVisibility(View.INVISIBLE);
- PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
-
- mOriginatingUid = getOriginatingUid(intent);
+ mOk = (Button)findViewById(R.id.ok_button);
+ mCancel = (Button)findViewById(R.id.cancel_button);
+ mOk.setOnClickListener(this);
+ mCancel.setOnClickListener(this);
// Block the install attempt on the Unknown Sources setting if necessary.
final boolean requestFromUnknownSource = isInstallRequestFromUnknownSource(intent);
@@ -517,17 +499,87 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
// If the admin prohibits it, or we're running in a managed profile, just show error
// and exit. Otherwise show an option to take the user to Settings to change the setting.
final boolean isManagedProfile = mUserManager.isManagedProfile();
- if (!unknownSourcesAllowedByAdmin) {
+ if (!isUnknownSourcesAllowedByAdmin()) {
startActivity(new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS));
- finish();
- } else if (!unknownSourcesAllowedByUser && isManagedProfile) {
+ clearCachedApkIfNeededAndFinish();
+ } else if (!isUnknownSourcesEnabled() && isManagedProfile) {
showDialogInner(DLG_ADMIN_RESTRICTS_UNKNOWN_SOURCES);
- } else if (!unknownSourcesAllowedByUser) {
+ } else if (!isUnknownSourcesEnabled()) {
// Ask user to enable setting first
showDialogInner(DLG_UNKNOWN_SOURCES);
- } else {
- initiateInstall();
}
+
+ processPackageUri(packageUri);
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (mStagingAsynTask != null) {
+ mStagingAsynTask.cancel(true);
+ mStagingAsynTask = null;
+ }
+ super.onDestroy();
+ }
+
+ private void processPackageUri(final Uri packageUri) {
+ mPackageURI = packageUri;
+
+ final String scheme = packageUri.getScheme();
+ final PackageUtil.AppSnippet as;
+
+ switch (scheme) {
+ case SCHEME_PACKAGE: {
+ try {
+ mPkgInfo = mPm.getPackageInfo(packageUri.getSchemeSpecificPart(),
+ PackageManager.GET_PERMISSIONS
+ | PackageManager.GET_UNINSTALLED_PACKAGES);
+ } catch (NameNotFoundException e) {
+ }
+ if (mPkgInfo == null) {
+ Log.w(TAG, "Requested package " + packageUri.getScheme()
+ + " not available. Discontinuing installation");
+ showDialogInner(DLG_PACKAGE_ERROR);
+ setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
+ return;
+ }
+ as = new PackageUtil.AppSnippet(mPm.getApplicationLabel(mPkgInfo.applicationInfo),
+ mPm.getApplicationIcon(mPkgInfo.applicationInfo));
+ } break;
+
+ case SCHEME_FILE: {
+ File sourceFile = new File(packageUri.getPath());
+ PackageParser.Package parsed = PackageUtil.getPackageInfo(sourceFile);
+
+ // Check for parse errors
+ if (parsed == null) {
+ Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
+ showDialogInner(DLG_PACKAGE_ERROR);
+ setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
+ return;
+ }
+ mPkgInfo = PackageParser.generatePackageInfo(parsed, null,
+ PackageManager.GET_PERMISSIONS, 0, 0, null,
+ new PackageUserState());
+ as = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
+ } break;
+
+ case SCHEME_CONTENT: {
+ mStagingAsynTask = new StagingAsyncTask();
+ mStagingAsynTask.execute(packageUri);
+ return;
+ }
+
+ default: {
+ Log.w(TAG, "Unsupported scheme " + scheme);
+ setPmResult(PackageManager.INSTALL_FAILED_INVALID_URI);
+ clearCachedApkIfNeededAndFinish();
+ return;
+ }
+ }
+
+ PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
+
+ initiateInstall();
}
/** Get the ApplicationInfo for the calling package, if available */
@@ -612,7 +664,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
// Generic handling when pressing back key
public void onCancel(DialogInterface dialog) {
- finish();
+ clearCachedApkIfNeededAndFinish();
}
public void onClick(View v) {
@@ -620,7 +672,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
if (mOkCanInstall || mScrollView == null) {
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
- finish();
+ clearCachedApkIfNeededAndFinish();
} else {
startInstall();
}
@@ -633,7 +685,7 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, false);
}
- finish();
+ clearCachedApkIfNeededAndFinish();
}
}
@@ -664,7 +716,99 @@ public class PackageInstallerActivity extends Activity implements OnCancelListen
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
}
if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
- startActivity(newIntent);
+ startActivityForResult(newIntent, REQUEST_INSTALL_PACKAGE);
+ }
+
+ private void clearCachedApkIfNeededAndFinish() {
+ if (mContentUriApkStagingFile != null) {
+ mContentUriApkStagingFile.delete();
+ mContentUriApkStagingFile = null;
+ }
finish();
}
+
+ private final class StagingAsyncTask extends AsyncTask<Uri, Void, File> {
+ private static final long SHOW_EMPTY_STATE_DELAY_MILLIS = 300;
+
+ private final Runnable mEmptyStateRunnable = new Runnable() {
+ @Override
+ public void run() {
+ ((TextView) findViewById(R.id.app_name)).setText(R.string.app_name_unknown);
+ ((TextView) findViewById(R.id.install_confirm_question))
+ .setText(R.string.message_staging);
+ mInstallConfirm.setVisibility(View.VISIBLE);
+ findViewById(android.R.id.tabhost).setVisibility(View.INVISIBLE);
+ findViewById(R.id.ok_button).setEnabled(false);
+ Drawable icon = getDrawable(R.drawable.ic_file_download);
+ Utils.applyTint(PackageInstallerActivity.this,
+ icon, android.R.attr.colorControlNormal);
+ ((ImageView) findViewById(R.id.app_icon)).setImageDrawable(icon);
+ }
+ };
+
+ @Override
+ protected void onPreExecute() {
+ getWindow().getDecorView().postDelayed(mEmptyStateRunnable,
+ SHOW_EMPTY_STATE_DELAY_MILLIS);
+ }
+
+ @Override
+ protected File doInBackground(Uri... params) {
+ if (params == null || params.length <= 0) {
+ return null;
+ }
+ Uri packageUri = params[0];
+ File sourceFile = null;
+ try {
+ sourceFile = File.createTempFile("package", ".apk", getCacheDir());
+ try (
+ InputStream in = getContentResolver().openInputStream(packageUri);
+ OutputStream out = (in != null) ? new FileOutputStream(
+ sourceFile) : null;
+ ) {
+ // Despite the comments in ContentResolver#openInputStream
+ // the returned stream can be null.
+ if (in == null) {
+ return null;
+ }
+ byte[] buffer = new byte[4096];
+ int bytesRead;
+ while ((bytesRead = in.read(buffer)) >= 0) {
+ // Be nice and respond to a cancellation
+ if (isCancelled()) {
+ return null;
+ }
+ out.write(buffer, 0, bytesRead);
+ }
+ }
+ } catch (IOException ioe) {
+ Log.w(TAG, "Error staging apk from content URI", ioe);
+ if (sourceFile != null) {
+ sourceFile.delete();
+ }
+ }
+ return sourceFile;
+ }
+
+ @Override
+ protected void onPostExecute(File file) {
+ getWindow().getDecorView().removeCallbacks(mEmptyStateRunnable);
+ if (isFinishing() || isDestroyed()) {
+ return;
+ }
+ if (file == null) {
+ showDialogInner(DLG_PACKAGE_ERROR);
+ setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
+ return;
+ }
+ mContentUriApkStagingFile = file;
+ Uri fileUri = Uri.fromFile(file);
+ processPackageUri(fileUri);
+ }
+
+ @Override
+ protected void onCancelled(File file) {
+ getWindow().getDecorView().removeCallbacks(mEmptyStateRunnable);
+ }
+ };
}
diff --git a/src/com/android/packageinstaller/UninstallAppProgress.java b/src/com/android/packageinstaller/UninstallAppProgress.java
index 4c039051..f1c569a7 100755
--- a/src/com/android/packageinstaller/UninstallAppProgress.java
+++ b/src/com/android/packageinstaller/UninstallAppProgress.java
@@ -35,6 +35,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
@@ -64,6 +65,7 @@ public class UninstallAppProgress extends Activity implements OnClickListener {
private TextView mStatusTextView;
private Button mOkButton;
private Button mDeviceManagerButton;
+ private Button mUsersButton;
private ProgressBar mProgressBar;
private View mOkPanel;
private volatile int mResultCode = -1;
@@ -180,6 +182,7 @@ public class UninstallAppProgress extends Activity implements OnClickListener {
mDeviceManagerButton.setVisibility(View.VISIBLE);
} else {
mDeviceManagerButton.setVisibility(View.GONE);
+ mUsersButton.setVisibility(View.VISIBLE);
}
// TODO: b/25442806
if (blockingUserId == UserHandle.USER_SYSTEM) {
@@ -260,6 +263,7 @@ public class UninstallAppProgress extends Activity implements OnClickListener {
mStatusTextView = (TextView) findViewById(R.id.center_text);
mStatusTextView.setText(R.string.uninstalling);
mDeviceManagerButton = (Button) findViewById(R.id.device_manager_button);
+ mUsersButton = (Button) findViewById(R.id.users_button);
mDeviceManagerButton.setVisibility(View.GONE);
mDeviceManagerButton.setOnClickListener(new OnClickListener() {
@Override
@@ -272,6 +276,16 @@ public class UninstallAppProgress extends Activity implements OnClickListener {
finish();
}
});
+ mUsersButton.setVisibility(View.GONE);
+ mUsersButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(Settings.ACTION_USER_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ finish();
+ }
+ });
mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
mProgressBar.setIndeterminate(true);
// Hide button till progress is being displayed
diff --git a/src/com/android/packageinstaller/UninstallerActivity.java b/src/com/android/packageinstaller/UninstallerActivity.java
index f1afe424..ae1659f4 100755
--- a/src/com/android/packageinstaller/UninstallerActivity.java
+++ b/src/com/android/packageinstaller/UninstallerActivity.java
@@ -74,11 +74,15 @@ public class UninstallerActivity extends Activity {
final boolean isUpdate =
((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
+ UserManager userManager = UserManager.get(getActivity());
if (isUpdate) {
- messageBuilder.append(getString(R.string.uninstall_update_text));
+ if (isSingleUser(userManager)) {
+ messageBuilder.append(getString(R.string.uninstall_update_text));
+ } else {
+ messageBuilder.append(getString(R.string.uninstall_update_text_multiuser));
+ }
} else {
- UserManager userManager = UserManager.get(getActivity());
- if (dialogInfo.allUsers && userManager.getUserCount() >= 2) {
+ if (dialogInfo.allUsers && !isSingleUser(userManager)) {
messageBuilder.append(getString(R.string.uninstall_application_text_all_users));
} else if (!dialogInfo.user.equals(android.os.Process.myUserHandle())) {
UserInfo userInfo = userManager.getUserInfo(dialogInfo.user.getIdentifier());
@@ -113,6 +117,16 @@ public class UninstallerActivity extends Activity {
getActivity().finish();
}
}
+
+ /**
+ * Returns whether there is only one user on this device, not including
+ * the system-only user.
+ */
+ private boolean isSingleUser(UserManager userManager) {
+ final int userCount = userManager.getUserCount();
+ return userCount == 1
+ || (UserManager.isSplitSystemUser() && userCount == 2);
+ }
}
public static class AppNotFoundDialogFragment extends DialogFragment {
diff --git a/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java b/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java
index 99621a7a..214571ba 100644
--- a/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java
+++ b/src/com/android/packageinstaller/permission/model/AppPermissionGroup.java
@@ -162,6 +162,10 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
group.addPermission(permission);
}
+ if (group.getPermissions().isEmpty()) {
+ return null;
+ }
+
return group;
}
@@ -211,6 +215,9 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
}
public boolean isReviewRequired() {
+ if (mAppSupportsRuntimePermissions) {
+ return false;
+ }
final int permissionCount = mPermissions.size();
for (int i = 0; i < permissionCount; i++) {
Permission permission = mPermissions.valueAt(i);
@@ -246,17 +253,6 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
return false;
}
- public boolean hasAppOpPermission() {
- final int permissionCount = mPermissions.size();
- for (int i = 0; i < permissionCount; i++) {
- Permission permission = mPermissions.valueAt(i);
- if (permission.getAppOp() != AppOpsManager.OP_NONE) {
- return true;
- }
- }
- return false;
- }
-
public PackageInfo getApp() {
return mPackageInfo;
}
@@ -312,9 +308,8 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
if (permission.isGranted()) {
return true;
}
- } else if (permission.isGranted() && ((permission.getAppOp()
- == AppOpsManager.OP_NONE || permission.isAppOpAllowed()))
- && !permission.isReviewRequired()) {
+ } else if (permission.isGranted() && (permission.getAppOp()
+ == AppOpsManager.OP_NONE || permission.isAppOpAllowed())) {
return true;
}
}
diff --git a/src/com/android/packageinstaller/permission/model/AppPermissions.java b/src/com/android/packageinstaller/permission/model/AppPermissions.java
index ca28ab41..e455ef13 100644
--- a/src/com/android/packageinstaller/permission/model/AppPermissions.java
+++ b/src/com/android/packageinstaller/permission/model/AppPermissions.java
@@ -32,16 +32,6 @@ import java.util.LinkedHashMap;
import java.util.List;
public final class AppPermissions {
- private static final float MAX_APP_LABEL_LENGTH_PIXELS = 500;
-
- private static final TextPaint sAppLabelEllipsizePaint = new TextPaint();
- static {
- sAppLabelEllipsizePaint.setAntiAlias(true);
- // Both text size and width are given in absolute pixels, for consistent truncation
- // across devices; this value corresponds to the default 14dip size on an xdhpi device.
- sAppLabelEllipsizePaint.setTextSize(42);
- }
-
private final ArrayList<AppPermissionGroup> mGroups = new ArrayList<>();
private final LinkedHashMap<String, AppPermissionGroup> mNameToGroupMap = new LinkedHashMap<>();
@@ -63,7 +53,9 @@ public final class AppPermissions {
mContext = context;
mPackageInfo = packageInfo;
mFilterPermissions = permissions;
- mAppLabel = loadEllipsizedAppLabel(context, packageInfo);
+ mAppLabel = BidiFormatter.getInstance().unicodeWrap(
+ packageInfo.applicationInfo.loadSafeLabel(
+ context.getPackageManager()).toString());
mSortGroups = sortGroups;
mOnErrorCallback = onErrorCallback;
loadPermissionGroups();
@@ -177,16 +169,4 @@ public final class AppPermissions {
}
return false;
}
-
- private static CharSequence loadEllipsizedAppLabel(Context context, PackageInfo packageInfo) {
- String label = packageInfo.applicationInfo.loadLabel(
- context.getPackageManager()).toString();
- String ellipsizedLabel = label.replace("\n", " ");
- if (!DeviceUtils.isWear(context)) {
- // Only ellipsize for non-Wear devices.
- ellipsizedLabel = TextUtils.ellipsize(ellipsizedLabel, sAppLabelEllipsizePaint,
- MAX_APP_LABEL_LENGTH_PIXELS, TextUtils.TruncateAt.END).toString();
- }
- return BidiFormatter.getInstance().unicodeWrap(ellipsizedLabel);
- }
}
diff --git a/src/com/android/packageinstaller/permission/model/PermissionApps.java b/src/com/android/packageinstaller/permission/model/PermissionApps.java
index 9ff5025c..2c0508a5 100644
--- a/src/com/android/packageinstaller/permission/model/PermissionApps.java
+++ b/src/com/android/packageinstaller/permission/model/PermissionApps.java
@@ -32,7 +32,7 @@ import android.util.Log;
import android.util.SparseArray;
import com.android.packageinstaller.R;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/com/android/packageinstaller/permission/model/PermissionGroups.java b/src/com/android/packageinstaller/permission/model/PermissionGroups.java
index 8ca69f24..04dd07ff 100644
--- a/src/com/android/packageinstaller/permission/model/PermissionGroups.java
+++ b/src/com/android/packageinstaller/permission/model/PermissionGroups.java
@@ -31,7 +31,7 @@ import android.os.Bundle;
import android.util.ArraySet;
import com.android.packageinstaller.R;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/com/android/packageinstaller/permission/model/PermissionStatusReceiver.java b/src/com/android/packageinstaller/permission/model/PermissionStatusReceiver.java
index 810ae8ec..d7e4547a 100644
--- a/src/com/android/packageinstaller/permission/model/PermissionStatusReceiver.java
+++ b/src/com/android/packageinstaller/permission/model/PermissionStatusReceiver.java
@@ -26,7 +26,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.text.Collator;
import java.util.ArrayList;
diff --git a/src/com/android/packageinstaller/permission/ui/ReviewPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/ReviewPermissionsActivity.java
index b872983d..2bff0e28 100644
--- a/src/com/android/packageinstaller/permission/ui/ReviewPermissionsActivity.java
+++ b/src/com/android/packageinstaller/permission/ui/ReviewPermissionsActivity.java
@@ -46,7 +46,7 @@ import android.widget.TextView;
import com.android.packageinstaller.R;
import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.AppPermissions;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import com.android.packageinstaller.permission.ui.ConfirmActionDialogFragment.OnActionConfirmedListener;
import java.util.List;
@@ -120,13 +120,18 @@ public final class ReviewPermissionsActivity extends Activity
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
PackageInfo packageInfo = getArguments().getParcelable(EXTRA_PACKAGE_INFO);
if (packageInfo == null) {
- getActivity().finish();
+ activity.finish();
return;
}
- mAppPermissions = new AppPermissions(getActivity(), packageInfo, null, false,
+ mAppPermissions = new AppPermissions(activity, packageInfo, null, false,
new Runnable() {
@Override
public void run() {
@@ -135,11 +140,11 @@ public final class ReviewPermissionsActivity extends Activity
});
if (mAppPermissions.getPermissionGroups().isEmpty()) {
- getActivity().finish();
+ activity.finish();
return;
}
- boolean reviewRequired= false;
+ boolean reviewRequired = false;
for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) {
if (group.isReviewRequired()) {
reviewRequired = true;
@@ -148,7 +153,7 @@ public final class ReviewPermissionsActivity extends Activity
}
if (!reviewRequired) {
- getActivity().finish();
+ activity.finish();
}
}
@@ -161,19 +166,24 @@ public final class ReviewPermissionsActivity extends Activity
@Override
public void onResume() {
super.onResume();
+ mAppPermissions.refresh();
loadPreferences();
}
@Override
public void onClick(View view) {
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
if (view == mContinueButton) {
confirmPermissionsReview();
executeCallback(true);
} else if (view == mCancelButton) {
executeCallback(false);
- getActivity().setResult(Activity.RESULT_CANCELED);
+ activity.setResult(Activity.RESULT_CANCELED);
}
- getActivity().finish();
+ activity.finish();
}
@Override
@@ -185,6 +195,8 @@ public final class ReviewPermissionsActivity extends Activity
SwitchPreference switchPreference = (SwitchPreference) preference;
if (switchPreference.isChecked()) {
showWarnRevokeDialog(switchPreference.getKey());
+ } else {
+ return true;
}
}
return false;
@@ -229,6 +241,9 @@ public final class ReviewPermissionsActivity extends Activity
private void bindUi() {
Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
// Set icon
Drawable icon = mAppPermissions.getPackageInfo().applicationInfo.loadIcon(
@@ -268,6 +283,11 @@ public final class ReviewPermissionsActivity extends Activity
}
private void loadPreferences() {
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+
PreferenceScreen screen = getPreferenceScreen();
if (screen == null) {
screen = getPreferenceManager().createPreferenceScreen(getActivity());
@@ -298,17 +318,8 @@ public final class ReviewPermissionsActivity extends Activity
} else {
preference = new SwitchPreference(getActivity());
- // We update permission grants based on the final preference states
- if (group.isReviewRequired()) {
- // If review is required use granted as default
- preference.setChecked(true);
- } else {
- // If review not required use the current grant state as default
- preference.setChecked(group.areRuntimePermissionsGranted());
- }
-
preference.setKey(group.getName());
- Drawable icon = Utils.loadDrawable(getActivity().getPackageManager(),
+ Drawable icon = Utils.loadDrawable(activity.getPackageManager(),
group.getIconPkg(), group.getIconResId());
preference.setIcon(Utils.applyTint(getContext(), icon,
android.R.attr.colorControlNormal));
@@ -319,6 +330,8 @@ public final class ReviewPermissionsActivity extends Activity
preference.setOnPreferenceChangeListener(this);
}
+ preference.setChecked(group.areRuntimePermissionsGranted());
+
// Mutable state
if (group.isPolicyFixed()) {
preference.setEnabled(false);
@@ -333,7 +346,7 @@ public final class ReviewPermissionsActivity extends Activity
screen.addPreference(preference);
} else {
if (mNewPermissionsCategory == null) {
- mNewPermissionsCategory = new PreferenceCategory(getActivity());
+ mNewPermissionsCategory = new PreferenceCategory(activity);
mNewPermissionsCategory.setTitle(R.string.new_permissions_category);
mNewPermissionsCategory.setOrder(1);
screen.addPreference(mNewPermissionsCategory);
@@ -342,7 +355,7 @@ public final class ReviewPermissionsActivity extends Activity
}
} else {
if (currentPermissionsCategory == null) {
- currentPermissionsCategory = new PreferenceCategory(getActivity());
+ currentPermissionsCategory = new PreferenceCategory(activity);
currentPermissionsCategory.setTitle(R.string.current_permissions_category);
currentPermissionsCategory.setOrder(2);
screen.addPreference(currentPermissionsCategory);
@@ -366,6 +379,9 @@ public final class ReviewPermissionsActivity extends Activity
private void executeCallback(boolean success) {
Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
if (success) {
IntentSender intent = activity.getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
if (intent != null) {
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java
index 0c249e55..540d8765 100644
--- a/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/handheld/AllAppPermissionsFragment.java
@@ -37,7 +37,7 @@ import android.provider.Settings;
import android.util.Log;
import android.view.MenuItem;
import com.android.packageinstaller.R;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java
index 925cacf3..5ecc7ab2 100644
--- a/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java
@@ -49,10 +49,9 @@ import android.widget.Toast;
import com.android.packageinstaller.R;
import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.AppPermissions;
-import com.android.packageinstaller.permission.ui.OverlayTouchActivity;
import com.android.packageinstaller.permission.utils.LocationUtils;
import com.android.packageinstaller.permission.utils.SafetyNetLogger;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import com.android.settingslib.RestrictedLockUtils;
import java.util.ArrayList;
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java
index c53da879..f5d7020e 100644
--- a/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/handheld/ManagePermissionsFragment.java
@@ -37,7 +37,7 @@ import com.android.packageinstaller.permission.model.PermissionApps;
import com.android.packageinstaller.permission.model.PermissionApps.PmCache;
import com.android.packageinstaller.permission.model.PermissionGroup;
import com.android.packageinstaller.permission.model.PermissionGroups;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.util.List;
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java
index 099c78b6..0fb1ad52 100644
--- a/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/handheld/PermissionAppsFragment.java
@@ -43,10 +43,9 @@ import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.PermissionApps;
import com.android.packageinstaller.permission.model.PermissionApps.Callback;
import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp;
-import com.android.packageinstaller.permission.ui.OverlayTouchActivity;
import com.android.packageinstaller.permission.utils.LocationUtils;
import com.android.packageinstaller.permission.utils.SafetyNetLogger;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import com.android.settingslib.RestrictedLockUtils;
import java.util.ArrayList;
@@ -228,7 +227,8 @@ public final class PermissionAppsFragment extends PermissionsFrameFragment imple
if (!isTelevision && (existingPref instanceof RestrictedSwitchPreference)) {
((RestrictedSwitchPreference) existingPref).setDisabledByAdmin(
isPolicyFixed ? enforcedAdmin : null);
- existingPref.setSummary(R.string.disabled_by_admin_summary_text);
+ existingPref.setSummary(isPolicyFixed ?
+ getString(R.string.disabled_by_admin_summary_text) : null);
} else {
existingPref.setEnabled(!isPolicyFixed);
existingPref.setSummary(isPolicyFixed ?
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java b/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java
index 8ab04807..44a7f471 100644
--- a/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java
+++ b/src/com/android/packageinstaller/permission/ui/handheld/RestrictedSwitchPreference.java
@@ -32,20 +32,26 @@ public class RestrictedSwitchPreference extends SwitchPreference {
private final Context mContext;
private boolean mDisabledByAdmin;
private EnforcedAdmin mEnforcedAdmin;
+ private final int mSwitchWidgetResId;
public RestrictedSwitchPreference(Context context) {
super(context);
+ mSwitchWidgetResId = getWidgetLayoutResource();
mContext = context;
}
@Override
public void onBindView(View view) {
super.onBindView(view);
- final TextView textView = (TextView) view.findViewById(android.R.id.title);
- if (textView != null) {
- RestrictedLockUtils.setTextViewPadlock(mContext, textView, mDisabledByAdmin);
- if (mDisabledByAdmin) {
- view.setEnabled(true);
+ if (mDisabledByAdmin) {
+ view.setEnabled(true);
+ }
+ if (mDisabledByAdmin) {
+ final TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
+ if (summaryView != null) {
+ summaryView.setText(
+ isChecked() ? R.string.enabled_by_admin : R.string.disabled_by_admin);
+ summaryView.setVisibility(View.VISIBLE);
}
}
}
@@ -64,6 +70,7 @@ public class RestrictedSwitchPreference extends SwitchPreference {
mEnforcedAdmin = admin;
if (mDisabledByAdmin != disabled) {
mDisabledByAdmin = disabled;
+ setWidgetLayoutResource(disabled ? R.layout.restricted_icon : mSwitchWidgetResId);
setEnabled(!disabled);
}
}
diff --git a/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java b/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java
index c15a4287..d5775796 100644
--- a/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java
+++ b/src/com/android/packageinstaller/permission/ui/handheld/SettingsWithHeader.java
@@ -28,7 +28,6 @@ import android.widget.TextView;
import com.android.packageinstaller.DeviceUtils;
import com.android.packageinstaller.R;
-import com.android.packageinstaller.permission.utils.Utils;
public abstract class SettingsWithHeader extends PermissionsFrameFragment
implements OnClickListener {
diff --git a/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java
index 7ea9a258..db99538c 100644
--- a/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/AllAppPermissionsFragment.java
@@ -45,7 +45,7 @@ import android.view.MenuItem;
import com.android.packageinstaller.R;
import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.AppPermissions;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java
index 1a078e50..afd2fcc5 100644
--- a/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/AppPermissionsFragment.java
@@ -50,11 +50,10 @@ import android.widget.Toast;
import com.android.packageinstaller.R;
import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.AppPermissions;
-import com.android.packageinstaller.permission.ui.OverlayTouchActivity;
import com.android.packageinstaller.permission.ui.ReviewPermissionsActivity;
import com.android.packageinstaller.permission.utils.LocationUtils;
import com.android.packageinstaller.permission.utils.SafetyNetLogger;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java
index 47301f48..81550337 100644
--- a/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/ManagePermissionsFragment.java
@@ -38,7 +38,7 @@ import com.android.packageinstaller.permission.model.PermissionApps;
import com.android.packageinstaller.permission.model.PermissionApps.PmCache;
import com.android.packageinstaller.permission.model.PermissionGroup;
import com.android.packageinstaller.permission.model.PermissionGroups;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.util.List;
diff --git a/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java
index acaadcaa..5a3346fc 100644
--- a/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/PermissionAppsFragment.java
@@ -45,11 +45,10 @@ import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.PermissionApps;
import com.android.packageinstaller.permission.model.PermissionApps.Callback;
import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp;
-import com.android.packageinstaller.permission.ui.OverlayTouchActivity;
import com.android.packageinstaller.permission.ui.ReviewPermissionsActivity;
import com.android.packageinstaller.permission.utils.LocationUtils;
import com.android.packageinstaller.permission.utils.SafetyNetLogger;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java b/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java
index e81aee86..2c7b91e9 100644
--- a/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/television/PermissionsFrameFragment.java
@@ -33,7 +33,6 @@ import android.widget.TextView;
import com.android.packageinstaller.DeviceUtils;
import com.android.packageinstaller.R;
-import com.android.packageinstaller.permission.utils.Utils;
public abstract class PermissionsFrameFragment extends PreferenceFragment {
diff --git a/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java b/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java
index 4dae629c..a401426d 100644
--- a/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java
+++ b/src/com/android/packageinstaller/permission/ui/television/SettingsWithHeader.java
@@ -28,7 +28,6 @@ import android.widget.TextView;
import com.android.packageinstaller.DeviceUtils;
import com.android.packageinstaller.R;
-import com.android.packageinstaller.permission.utils.Utils;
public abstract class SettingsWithHeader extends PermissionsFrameFragment
implements OnClickListener {
diff --git a/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java b/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java
index 6ea34628..4b621a64 100644
--- a/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java
+++ b/src/com/android/packageinstaller/permission/ui/wear/AppPermissionsFragmentWear.java
@@ -35,12 +35,11 @@ import android.widget.Toast;
import com.android.packageinstaller.R;
import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.AppPermissions;
-import com.android.packageinstaller.permission.ui.OverlayTouchActivity;
import com.android.packageinstaller.permission.ui.wear.settings.PermissionsSettingsAdapter;
import com.android.packageinstaller.permission.ui.wear.settings.SettingsAdapter;
import com.android.packageinstaller.permission.utils.LocationUtils;
import com.android.packageinstaller.permission.utils.SafetyNetLogger;
-import com.android.packageinstaller.permission.utils.Utils;
+import com.android.packageinstaller.util.Utils;
import java.util.ArrayList;
import java.util.List;
@@ -124,18 +123,18 @@ public final class AppPermissionsFragmentWear extends TitledSettingsFragment {
super.onViewCreated(view, savedInstanceState);
if (mAppPermissions != null) {
initializeLayout(mAdapter);
- bindHeader(mAppPermissions.getPackageInfo());
+ mHeader.setText(R.string.app_permissions);
+ mDetails.setText(R.string.no_permissions);
+ if (mAdapter.getItemCount() == 0) {
+ mDetails.setVisibility(View.VISIBLE);
+ mWheel.setVisibility(View.GONE);
+ } else {
+ mDetails.setVisibility(View.GONE);
+ mWheel.setVisibility(View.VISIBLE);
+ }
}
}
- private void bindHeader(PackageInfo packageInfo) {
- Activity activity = getActivity();
- PackageManager pm = activity.getPackageManager();
- ApplicationInfo appInfo = packageInfo.applicationInfo;
- CharSequence label = appInfo.loadLabel(pm);
- mHeader.setText(label);
- }
-
private void initializePermissionGroupList() {
final String packageName = mAppPermissions.getPackageInfo().packageName;
List<AppPermissionGroup> groups = mAppPermissions.getPermissionGroups();
diff --git a/src/com/android/packageinstaller/permission/ui/wear/TitledSettingsFragment.java b/src/com/android/packageinstaller/permission/ui/wear/TitledSettingsFragment.java
index ef7efb28..b673a498 100644
--- a/src/com/android/packageinstaller/permission/ui/wear/TitledSettingsFragment.java
+++ b/src/com/android/packageinstaller/permission/ui/wear/TitledSettingsFragment.java
@@ -28,7 +28,7 @@ import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
-import android.widget.FrameLayout;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.packageinstaller.permission.ui.wear.settings.ViewUtils;
@@ -46,6 +46,7 @@ public abstract class TitledSettingsFragment extends Fragment implements
private int mInitialHeaderHeight;
protected TextView mHeader;
+ protected TextView mDetails;
protected WearableListView mWheel;
private int mCharLimitShortTitle;
@@ -114,6 +115,9 @@ public abstract class TitledSettingsFragment extends Fragment implements
mHeader.addOnLayoutChangeListener(this);
mHeader.addTextChangedListener(mHeaderTextWatcher);
+ mDetails = (TextView) v.findViewById(R.id.details);
+ mDetails.addOnLayoutChangeListener(this);
+
mWheel.setAdapter(adapter);
mWheel.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
@@ -134,13 +138,14 @@ public abstract class TitledSettingsFragment extends Fragment implements
adjustHeaderSize();
- positionOnCircular(getContext(), mHeader, mWheel);
+ positionOnCircular(getContext(), mHeader, mDetails, mWheel);
}
- public void positionOnCircular(Context context, View header, final ViewGroup wheel) {
+ public void positionOnCircular(Context context, View header, View details,
+ final ViewGroup wheel) {
if (ViewUtils.getIsCircular(context)) {
- FrameLayout.LayoutParams params =
- (FrameLayout.LayoutParams) header.getLayoutParams();
+ LinearLayout.LayoutParams params =
+ (LinearLayout.LayoutParams) header.getLayoutParams();
params.topMargin = (int) context.getResources().getDimension(
R.dimen.settings_header_top_margin_circular);
// Note that the margins are made symmetrical here. Since they're symmetrical we choose
@@ -152,10 +157,14 @@ public abstract class TitledSettingsFragment extends Fragment implements
params.rightMargin = margin;
params.gravity = Gravity.CENTER_HORIZONTAL;
header.setLayoutParams(params);
+ details.setLayoutParams(params);
if (header instanceof TextView) {
((TextView) header).setGravity(Gravity.CENTER);
}
+ if (details instanceof TextView) {
+ ((TextView) details).setGravity(Gravity.CENTER);
+ }
final int leftPadding = (int) context.getResources().getDimension(
R.dimen.round_content_padding_left);
@@ -209,7 +218,7 @@ public abstract class TitledSettingsFragment extends Fragment implements
}
mHeader.setMinHeight((int) height);
- FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mHeader.getLayoutParams();
+ LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mHeader.getLayoutParams();
final Context context = getContext();
if (!singleLine) {
// Make the top margin a little bit smaller so there is more space for the title.
diff --git a/src/com/android/packageinstaller/permission/utils/Utils.java b/src/com/android/packageinstaller/util/Utils.java
index 21830378..f0d88d32 100644
--- a/src/com/android/packageinstaller/permission/utils/Utils.java
+++ b/src/com/android/packageinstaller/util/Utils.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.packageinstaller.permission.utils;
+package com.android.packageinstaller.util;
import android.Manifest;
import android.content.Context;
@@ -22,7 +22,6 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.graphics.drawable.Drawable;
@@ -33,6 +32,7 @@ import android.util.TypedValue;
import com.android.packageinstaller.permission.model.AppPermissionGroup;
import com.android.packageinstaller.permission.model.AppPermissions;
import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp;
+import com.android.packageinstaller.permission.utils.LocationUtils;
import java.util.List;
diff --git a/src/com/android/packageinstaller/wear/WearPackageArgs.java b/src/com/android/packageinstaller/wear/WearPackageArgs.java
index 67051da0..da49192a 100644
--- a/src/com/android/packageinstaller/wear/WearPackageArgs.java
+++ b/src/com/android/packageinstaller/wear/WearPackageArgs.java
@@ -25,6 +25,8 @@ import android.os.Bundle;
* installing/uninstalling.
*/
public class WearPackageArgs {
+ private static final String KEY_PACKAGE_NAME =
+ "com.google.android.clockwork.EXTRA_PACKAGE_NAME";
private static final String KEY_ASSET_URI =
"com.google.android.clockwork.EXTRA_ASSET_URI";
private static final String KEY_START_ID =
@@ -45,16 +47,16 @@ public class WearPackageArgs {
"com.google.android.clockwork.EXTRA_KEY_SHOULD_CHECK_GMS_DEPENDENCY";
public static String getPackageName(Bundle b) {
- return b.getString(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
+ return b.getString(KEY_PACKAGE_NAME);
}
- public static Uri getAssetUri(Bundle b) {
- return b.getParcelable(KEY_ASSET_URI);
+ public static Bundle setPackageName(Bundle b, String packageName) {
+ b.putString(KEY_PACKAGE_NAME, packageName);
+ return b;
}
- public static Bundle setAssetUri(Bundle b, Uri assetUri) {
- b.putParcelable(KEY_ASSET_URI, assetUri);
- return b;
+ public static Uri getAssetUri(Bundle b) {
+ return b.getParcelable(KEY_ASSET_URI);
}
public static Uri getPermUri(Bundle b) {
diff --git a/src/com/android/packageinstaller/wear/WearPackageInstallerService.java b/src/com/android/packageinstaller/wear/WearPackageInstallerService.java
index 3874c0a4..7387ed2a 100644
--- a/src/com/android/packageinstaller/wear/WearPackageInstallerService.java
+++ b/src/com/android/packageinstaller/wear/WearPackageInstallerService.java
@@ -66,13 +66,18 @@ import java.util.Set;
*
* Install Action example:
* adb shell am startservice -a com.android.packageinstaller.wear.INSTALL_PACKAGE \
- * -t vnd.android.cursor.item/wearable_apk \
- * -d content://com.google.android.clockwork.home.provider/host/com.google.android.wearable.app/wearable/com.google.android.gms/apk \
+ * -d package://com.google.android.gms \
+ * --eu com.google.android.clockwork.EXTRA_ASSET_URI content://com.google.android.clockwork.home.provider/host/com.google.android.wearable.app/wearable/com.google.android.gms/apk \
* --es android.intent.extra.INSTALLER_PACKAGE_NAME com.google.android.gms \
* --ez com.google.android.clockwork.EXTRA_CHECK_PERMS false \
* --eu com.google.android.clockwork.EXTRA_PERM_URI content://com.google.android.clockwork.home.provider/host/com.google.android.wearable.app/permissions \
* com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService
*
+ * Uninstall Action example:
+ * adb shell am startservice -a com.android.packageinstaller.wear.UNINSTALL_PACKAGE \
+ * -d package://com.google.android.gms \
+ * com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService
+ *
* Retry GMS:
* adb shell am startservice -a com.android.packageinstaller.wear.RETRY_GMS \
* com.android.packageinstaller/com.android.packageinstaller.wear.WearPackageInstallerService
@@ -141,29 +146,49 @@ public class WearPackageInstallerService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!DeviceUtils.isWear(this)) {
- Log.w(TAG, "Not running on wearable");
+ Log.w(TAG, "Not running on wearable.");
+ return START_NOT_STICKY;
+ }
+
+ if (intent == null) {
+ Log.w(TAG, "Got null intent.");
return START_NOT_STICKY;
}
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Got install/uninstall request " + intent);
+ }
+
+ Uri packageUri = intent.getData();
+ if (packageUri == null) {
+ Log.e(TAG, "No package URI in intent");
+ return START_NOT_STICKY;
+ }
+ final String packageName = WearPackageUtil.getSanitizedPackageName(packageUri);
+ if (packageName == null) {
+ Log.e(TAG, "Invalid package name in URI (expected package:<pkgName>): " + packageUri);
+ return START_NOT_STICKY;
+ }
+
PowerManager.WakeLock lock = getLock(this.getApplicationContext());
if (!lock.isHeld()) {
lock.acquire();
}
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Got install/uninstall request " + intent);
+
+ Bundle intentBundle = intent.getExtras();
+ if (intentBundle == null) {
+ intentBundle = new Bundle();
}
- if (intent != null) {
- Bundle intentBundle = intent.getExtras();
- WearPackageArgs.setStartId(intentBundle, startId);
- if (Intent.ACTION_INSTALL_PACKAGE.equals(intent.getAction())) {
- final Message msg = mServiceHandler.obtainMessage(START_INSTALL);
- WearPackageArgs.setAssetUri(intentBundle, intent.getData());
- msg.setData(intentBundle);
- mServiceHandler.sendMessage(msg);
- } else if (Intent.ACTION_UNINSTALL_PACKAGE.equals(intent.getAction())) {
- Message msg = mServiceHandler.obtainMessage(START_UNINSTALL);
- msg.setData(intentBundle);
- mServiceHandler.sendMessage(msg);
- }
+ WearPackageArgs.setStartId(intentBundle, startId);
+ WearPackageArgs.setPackageName(intentBundle, packageName);
+ if (Intent.ACTION_INSTALL_PACKAGE.equals(intent.getAction())) {
+ Message msg = mServiceHandler.obtainMessage(START_INSTALL);
+ msg.setData(intentBundle);
+ mServiceHandler.sendMessage(msg);
+ } else if (Intent.ACTION_UNINSTALL_PACKAGE.equals(intent.getAction())) {
+ Message msg = mServiceHandler.obtainMessage(START_UNINSTALL);
+ msg.setData(intentBundle);
+ mServiceHandler.sendMessage(msg);
}
return START_NOT_STICKY;
}
diff --git a/src/com/android/packageinstaller/wear/WearPackageUtil.java b/src/com/android/packageinstaller/wear/WearPackageUtil.java
index 688d6167..c351277e 100644
--- a/src/com/android/packageinstaller/wear/WearPackageUtil.java
+++ b/src/com/android/packageinstaller/wear/WearPackageUtil.java
@@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageParser;
+import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.Os;
@@ -164,4 +165,16 @@ public class WearPackageUtil {
+ " for " + wearablePackageName);
context.startService(newIntent);
}
+
+ /**
+ * @return com.google.com from expected formats like
+ * Uri: package:com.google.com, package:/com.google.com, package://com.google.com
+ */
+ public static String getSanitizedPackageName(Uri packageUri) {
+ String packageName = packageUri.getEncodedSchemeSpecificPart();
+ if (packageName != null) {
+ return packageName.replaceAll("^/+", "");
+ }
+ return packageName;
+ }
}