diff options
Diffstat (limited to 'src')
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; + } } |