diff options
37 files changed, 512 insertions, 84 deletions
diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp index 519852dbe88b..cdec6a01d086 100644 --- a/cmds/incident/main.cpp +++ b/cmds/incident/main.cpp @@ -148,9 +148,19 @@ find_section(const char* name) static int get_dest(const char* arg) { - if (strcmp(arg, "LOCAL") == 0) return 0; - if (strcmp(arg, "EXPLICIT") == 0) return 1; - if (strcmp(arg, "AUTOMATIC") == 0) return 2; + if (strcmp(arg, "L") == 0 + || strcmp(arg, "LOCAL") == 0) { + return DEST_LOCAL; + } + if (strcmp(arg, "E") == 0 + || strcmp(arg, "EXPLICIT") == 0) { + return DEST_EXPLICIT; + } + if (strcmp(arg, "A") == 0 + || strcmp(arg, "AUTO") == 0 + || strcmp(arg, "AUTOMATIC") == 0) { + return DEST_AUTOMATIC; + } return -1; // return the default value } diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp index 5db2239810e2..44adaecfe97f 100644 --- a/cmds/incidentd/src/Privacy.cpp +++ b/cmds/incidentd/src/Privacy.cpp @@ -67,8 +67,14 @@ PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; } PrivacySpec new_spec_from_args(int dest) { - if (dest < 0) return PrivacySpec(); - return PrivacySpec(dest); + switch (dest) { + case android::os::DEST_AUTOMATIC: + case android::os::DEST_EXPLICIT: + case android::os::DEST_LOCAL: + return PrivacySpec(dest); + default: + return PrivacySpec(); + } } PrivacySpec get_default_dropbox_spec() { return PrivacySpec(android::os::DEST_AUTOMATIC); }
\ No newline at end of file diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java index 998ac5f2a487..c34f4d9f0fe8 100644 --- a/core/java/android/app/LocalActivityManager.java +++ b/core/java/android/app/LocalActivityManager.java @@ -16,6 +16,8 @@ package android.app; +import android.app.ActivityThread.ActivityClientRecord; +import android.app.servertransaction.PendingTransactionActions; import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.Binder; @@ -141,6 +143,21 @@ public class LocalActivityManager { } r.window = r.activity.getWindow(); r.instanceState = null; + + final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r); + final PendingTransactionActions pendingActions; + + if (!r.activity.mFinished) { + // This matches pending actions set in ActivityThread#handleLaunchActivity + pendingActions = new PendingTransactionActions(); + pendingActions.setOldState(clientRecord.state); + pendingActions.setRestoreInstanceState(true); + pendingActions.setCallOnPostCreate(true); + } else { + pendingActions = null; + } + + mActivityThread.handleStartActivity(clientRecord, pendingActions); r.curState = STARTED; if (desiredState == RESUMED) { diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 746a090264c2..f6697e8148a0 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -602,6 +602,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public static final int PRIVATE_FLAG_VENDOR = 1 << 18; + /** + * Value for {@linl #privateFlags}: whether this app is pre-installed on the + * product partition of the system image. + * @hide + */ + public static final int PRIVATE_FLAG_PRODUCT = 1 << 19; + /** @hide */ @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = { PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE, @@ -619,6 +626,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { PRIVATE_FLAG_OEM, PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE, PRIVATE_FLAG_PRIVILEGED, + PRIVATE_FLAG_PRODUCT, PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, PRIVATE_FLAG_STATIC_SHARED_LIBRARY, PRIVATE_FLAG_VENDOR, @@ -1699,6 +1707,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; } + /** @hide */ + public boolean isProduct() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0; + } + /** * Returns whether or not this application was installed as a virtual preload. */ diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 3bb812b7ac83..d5c88aa1fbcb 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -6393,6 +6393,11 @@ public class PackageParser { } /** @hide */ + public boolean isProduct() { + return applicationInfo.isProduct(); + } + + /** @hide */ public boolean isPrivileged() { return applicationInfo.isPrivilegedApp(); } diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 158041dd91e7..03203d0502fd 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -41,6 +41,7 @@ public class Environment { private static final String ENV_OEM_ROOT = "OEM_ROOT"; private static final String ENV_ODM_ROOT = "ODM_ROOT"; private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT"; + private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT"; /** {@hide} */ public static final String DIR_ANDROID = "Android"; @@ -62,6 +63,7 @@ public class Environment { private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem"); private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm"); private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor"); + private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product"); private static UserEnvironment sCurrentUser; private static boolean sUserRequired; @@ -180,6 +182,16 @@ public class Environment { } /** + * Return root directory of the "product" partition holding product-specific + * customizations if any. If present, the partition is mounted read-only. + * + * @hide + */ + public static File getProductDirectory() { + return DIR_PRODUCT_ROOT; + } + + /** * Return the system directory for a user. This is for use by system * services to store files relating to the user. This directory will be * automatically deleted when the user is removed. diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index c5af89727575..111934f9d005 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -149,6 +149,9 @@ public class SystemConfig { final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>(); final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>(); + final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>(); + final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>(); + final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>(); public static SystemConfig getInstance() { @@ -240,6 +243,14 @@ public class SystemConfig { return mVendorPrivAppDenyPermissions.get(packageName); } + public ArraySet<String> getProductPrivAppPermissions(String packageName) { + return mProductPrivAppPermissions.get(packageName); + } + + public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) { + return mProductPrivAppDenyPermissions.get(packageName); + } + public Map<String, Boolean> getOemPermissions(String packageName) { final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName); if (oemPermissions != null) { @@ -278,6 +289,14 @@ public class SystemConfig { Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag); readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag); + + // Allow Product to customize system configs around libs, features, permissions and apps + int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS | + ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS; + readPermissions(Environment.buildPath( + Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag); + readPermissions(Environment.buildPath( + Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag); } void readPermissions(File libraryDir, int permissionFlag) { @@ -598,15 +617,20 @@ public class SystemConfig { } XmlUtils.skipCurrentTag(parser); } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) { - // privapp permissions from system and vendor partitions are stored + // privapp permissions from system, vendor and product partitions are stored // separately. This is to prevent xml files in the vendor partition from // granting permissions to priv apps in the system partition and vice // versa. boolean vendor = permFile.toPath().startsWith( Environment.getVendorDirectory().toPath()); + boolean product = permFile.toPath().startsWith( + Environment.getProductDirectory().toPath()); if (vendor) { readPrivAppPermissions(parser, mVendorPrivAppPermissions, mVendorPrivAppDenyPermissions); + } else if (product) { + readPrivAppPermissions(parser, mProductPrivAppPermissions, + mProductPrivAppDenyPermissions); } else { readPrivAppPermissions(parser, mPrivAppPermissions, mPrivAppDenyPermissions); diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 403937be7088..7e17a4909cee 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -174,6 +174,10 @@ static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) { argv[argc++] = AssetManager::OVERLAY_DIR; } + if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) { + argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR; + } + // Finally, invoke idmap (if any overlay directory exists) if (argc > 5) { execv(AssetManager::IDMAP_BIN, (char* const*)argv); diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp index 956b7249660f..3b7b14c58d0a 100644 --- a/core/jni/fd_utils.cpp +++ b/core/jni/fd_utils.cpp @@ -85,11 +85,15 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const { static const char* kOverlayDir = "/system/vendor/overlay/"; static const char* kVendorOverlayDir = "/vendor/overlay"; static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/"; + static const char* kSystemProductOverlayDir = "/system/product/overlay/"; + static const char* kProductOverlayDir = "/product/overlay"; static const char* kApkSuffix = ".apk"; if ((android::base::StartsWith(path, kOverlayDir) || android::base::StartsWith(path, kOverlaySubdir) - || android::base::StartsWith(path, kVendorOverlayDir)) + || android::base::StartsWith(path, kVendorOverlayDir) + || android::base::StartsWith(path, kSystemProductOverlayDir) + || android::base::StartsWith(path, kProductOverlayDir)) && android::base::EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) { return true; diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 0485625e81e8..a5698af18f6b 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -73,6 +73,7 @@ static volatile int32_t gCount = 0; const char* AssetManager::RESOURCES_FILENAME = "resources.arsc"; const char* AssetManager::IDMAP_BIN = "/system/bin/idmap"; const char* AssetManager::OVERLAY_DIR = "/vendor/overlay"; +const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay"; const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme"; const char* AssetManager::TARGET_PACKAGE_NAME = "android"; const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk"; diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h index ecc5dc1ad331..08da7319de85 100644 --- a/libs/androidfw/include/androidfw/AssetManager.h +++ b/libs/androidfw/include/androidfw/AssetManager.h @@ -60,6 +60,7 @@ public: static const char* RESOURCES_FILENAME; static const char* IDMAP_BIN; static const char* OVERLAY_DIR; + static const char* PRODUCT_OVERLAY_DIR; /* * If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay * APKs in OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java index 983ca754acd1..dcd4dce5f3eb 100644 --- a/media/java/android/media/MediaActionSound.java +++ b/media/java/android/media/MediaActionSound.java @@ -47,11 +47,16 @@ public class MediaActionSound { private SoundPool mSoundPool; private SoundState[] mSounds; + private static final String[] SOUND_DIRS = { + "/product/media/audio/ui/", + "/system/media/audio/ui/", + }; + private static final String[] SOUND_FILES = { - "/system/media/audio/ui/camera_click.ogg", - "/system/media/audio/ui/camera_focus.ogg", - "/system/media/audio/ui/VideoRecord.ogg", - "/system/media/audio/ui/VideoStop.ogg" + "camera_click.ogg", + "camera_focus.ogg", + "VideoRecord.ogg", + "VideoStop.ogg" }; private static final String TAG = "MediaActionSound"; @@ -132,12 +137,16 @@ public class MediaActionSound { } private int loadSound(SoundState sound) { - int id = mSoundPool.load(SOUND_FILES[sound.name], 1); - if (id > 0) { - sound.state = STATE_LOADING; - sound.id = id; + final String soundFileName = SOUND_FILES[sound.name]; + for (String soundDir : SOUND_DIRS) { + int id = mSoundPool.load(soundDir + soundFileName, 1); + if (id > 0) { + sound.state = STATE_LOADING; + sound.id = id; + return id; + } } - return id; + return 0; } /** diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index cb4e46fe945a..c3090389aa37 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -158,6 +158,7 @@ public class MediaScanner implements AutoCloseable { public static final String SCANNED_BUILD_PREFS_NAME = "MediaScanBuild"; public static final String LAST_INTERNAL_SCAN_FINGERPRINT = "lastScanFingerprint"; private static final String SYSTEM_SOUNDS_DIR = "/system/media/audio"; + private static final String PRODUCT_SOUNDS_DIR = "/product/media/audio"; private static String sLastInternalScanFingerprint; private static final String[] ID3_GENRES = { @@ -1153,7 +1154,10 @@ public class MediaScanner implements AutoCloseable { private static boolean isSystemSoundWithMetadata(String path) { if (path.startsWith(SYSTEM_SOUNDS_DIR + ALARMS_DIR) || path.startsWith(SYSTEM_SOUNDS_DIR + RINGTONES_DIR) - || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)) { + || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR) + || path.startsWith(PRODUCT_SOUNDS_DIR + ALARMS_DIR) + || path.startsWith(PRODUCT_SOUNDS_DIR + RINGTONES_DIR) + || path.startsWith(PRODUCT_SOUNDS_DIR + NOTIFICATIONS_DIR)) { return true; } return false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 1056ecc9bf6a..b3f68d357083 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -1472,7 +1472,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return mPrivateLayout.getActiveRemoteInputText(); } - public void animateTranslateNotification(final float leftTarget) { if (mTranslateAnim != null) { mTranslateAnim.cancel(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java index 8336d29f2870..907af690a615 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.app.ActivityManager; import android.app.ActivityOptions; import android.graphics.Matrix; import android.graphics.Rect; @@ -35,10 +36,11 @@ import android.view.ViewRootImpl; import com.android.systemui.Interpolators; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.NotificationListContainer; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; import com.android.systemui.statusbar.phone.NotificationPanelView; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarWindowView; -import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import java.util.function.Consumer; @@ -57,16 +59,17 @@ public class ActivityLaunchAnimator { private final NotificationPanelView mNotificationPanel; private final NotificationListContainer mNotificationContainer; private final StatusBarWindowView mStatusBarWindow; - private final Consumer<Boolean> mPanelCollapser; + private final StatusBar mStatusBar; + private boolean mAnimationPending; public ActivityLaunchAnimator(StatusBarWindowView statusBarWindow, - Consumer<Boolean> panelCollapser, + StatusBar statusBar, NotificationPanelView notificationPanel, NotificationListContainer container) { mNotificationPanel = notificationPanel; mNotificationContainer = container; mStatusBarWindow = statusBarWindow; - mPanelCollapser = panelCollapser; + mStatusBar = statusBar; } public ActivityOptions getLaunchAnimation( @@ -76,6 +79,21 @@ public class ActivityLaunchAnimator { new RemoteAnimationAdapter(animationRunner, 1000 /* Duration */, 0 /* delay */)); } + public boolean isAnimationPending() { + return mAnimationPending; + } + + public void setLaunchResult(int launchResult) { + setAnimationPending((launchResult == ActivityManager.START_TASK_TO_FRONT + || launchResult == ActivityManager.START_SUCCESS) + && mStatusBar.getBarState() == StatusBarState.SHADE); + } + + private void setAnimationPending(boolean pending) { + mAnimationPending = pending; + mStatusBarWindow.setExpandAnimationPending(pending); + } + class AnimationRunner extends IRemoteAnimationRunner.Stub { private final ExpandableNotificationRow mSourceNotification; @@ -94,7 +112,6 @@ public class ActivityLaunchAnimator { IRemoteAnimationFinishedCallback iRemoteAnimationFinishedCallback) throws RemoteException { mSourceNotification.post(() -> { - boolean first = true; for (RemoteAnimationTarget app : remoteAnimationTargets) { if (app.mode == RemoteAnimationTarget.MODE_OPENING) { setExpandAnimationRunning(true); @@ -139,7 +156,7 @@ public class ActivityLaunchAnimator { public void onAnimationEnd(Animator animation) { setExpandAnimationRunning(false); if (mInstantCollapsePanel) { - mPanelCollapser.accept(false /* animate */); + mStatusBar.collapsePanel(false /* animate */); } try { iRemoteAnimationFinishedCallback.onAnimationFinished(); @@ -152,6 +169,7 @@ public class ActivityLaunchAnimator { break; } } + setAnimationPending(false); }); } @@ -198,6 +216,10 @@ public class ActivityLaunchAnimator { @Override public void onAnimationCancelled() throws RemoteException { + mSourceNotification.post(() -> { + setAnimationPending(false); + mStatusBar.onLaunchAnimationCancelled(); + }); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index a62a424caaf5..2b7e4747a837 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -950,7 +950,7 @@ public abstract class PanelView extends FrameLayout { } public boolean isCollapsing() { - return mClosing; + return mClosing || mLaunchingNotification; } public boolean isTracking() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 7d8455002300..b51982415bbd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -100,7 +100,6 @@ import android.provider.Settings; import android.service.notification.StatusBarNotification; import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; -import android.text.SpannedString; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.EventLog; @@ -589,7 +588,7 @@ public class StatusBar extends SystemUI implements DemoMode, private NavigationBarFragment mNavigationBar; private View mNavigationBarView; - private ActivityLaunchAnimator mActivityLaunchAnimator; + protected ActivityLaunchAnimator mActivityLaunchAnimator; @Override public void start() { @@ -760,7 +759,7 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel); mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller); mActivityLaunchAnimator = new ActivityLaunchAnimator(mStatusBarWindow, - this::collapsePanel, + this, mNotificationPanel, mStackScroller); mGutsManager.setUpWithPresenter(this, mEntryManager, mStackScroller, mCheckSaveListener, @@ -2054,6 +2053,12 @@ public class StatusBar extends SystemUI implements DemoMode, } } + public void onLaunchAnimationCancelled() { + if (!isCollapsing()) { + onClosingFinished(); + } + } + /** * All changes to the status bar and notifications funnel through here and are batched. */ @@ -3418,7 +3423,7 @@ public class StatusBar extends SystemUI implements DemoMode, } public boolean isCollapsing() { - return mNotificationPanel.isCollapsing(); + return mNotificationPanel.isCollapsing() || mActivityLaunchAnimator.isAnimationPending(); } public void addPostCollapseAction(Runnable r) { @@ -4959,6 +4964,7 @@ public class StatusBar extends SystemUI implements DemoMode, try { launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null, null, null, getActivityOptions(row)); + mActivityLaunchAnimator.setLaunchResult(launchResult); } catch (PendingIntent.CanceledException e) { // the stack trace isn't very helpful here. // Just log the exception message. @@ -4970,7 +4976,7 @@ public class StatusBar extends SystemUI implements DemoMode, mAssistManager.hideAssist(); } } - if (shouldCollapse(launchResult)) { + if (shouldCollapse()) { if (Looper.getMainLooper().isCurrentThread()) { collapsePanel(); } else { @@ -5003,17 +5009,8 @@ public class StatusBar extends SystemUI implements DemoMode, }, afterKeyguardGone); } - private boolean shouldCollapse(int launchResult) { - return mState != StatusBarState.SHADE - || (launchResult != ActivityManager.START_TASK_TO_FRONT - && launchResult != ActivityManager.START_SUCCESS); - } - - public void onExpandAnimationFinished() { - if (!isPresenterFullyCollapsed()) { - instantCollapseNotificationPanel(); - visibilityChanged(false); - } + private boolean shouldCollapse() { + return mState != StatusBarState.SHADE || !mActivityLaunchAnimator.isAnimationPending(); } public void collapsePanel(boolean animate) { @@ -5128,7 +5125,8 @@ public class StatusBar extends SystemUI implements DemoMode, .addNextIntentWithParentStack(intent) .startActivities(getActivityOptions(row), new UserHandle(UserHandle.getUserId(appUid))); - if (shouldCollapse(launchResult)) { + mActivityLaunchAnimator.setLaunchResult(launchResult); + if (shouldCollapse()) { // Putting it back on the main thread, since we're touching views mStatusBarWindow.post(() -> animateCollapsePanels( CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index f7d0967c2378..e32914fa368b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -89,6 +89,7 @@ public class StatusBarWindowView extends FrameLayout { private boolean mTouchCancelled; private boolean mTouchActive; private boolean mExpandAnimationRunning; + private boolean mExpandAnimationPending; public StatusBarWindowView(Context context, AttributeSet attrs) { super(context, attrs); @@ -268,7 +269,7 @@ public class StatusBarWindowView extends FrameLayout { || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) { setTouchActive(false); } - if (mTouchCancelled || mExpandAnimationRunning) { + if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) { return false; } mFalsingManager.onTouchEvent(ev, getWidth(), getHeight()); @@ -393,6 +394,10 @@ public class StatusBarWindowView extends FrameLayout { mExpandAnimationRunning = expandAnimationRunning; } + public void setExpandAnimationPending(boolean pending) { + mExpandAnimationPending = pending; + } + public class LayoutParams extends FrameLayout.LayoutParams { public boolean ignoreRightInset; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java index 1e894ff4ee54..3febdfdfbe7e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java @@ -119,7 +119,8 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio // for the current foreground user. LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); - return locationManager.isLocationEnabledForUser(Process.myUserHandle()); + return locationManager.isLocationEnabledForUser( + UserHandle.of(ActivityManager.getCurrentUser())); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 99202f4ac10c..bdf9b1f6da9e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -84,6 +84,7 @@ import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -188,7 +189,8 @@ public class StatusBarTest extends SysuiTestCase { mKeyguardIndicationController, mStackScroller, mHeadsUpManager, mPowerManager, mNotificationPanelView, mBarService, mNotificationListener, mNotificationLogger, mVisualStabilityManager, mViewHierarchyManager, - mEntryManager, mScrimController, mFingerprintUnlockController); + mEntryManager, mScrimController, mFingerprintUnlockController, + mock(ActivityLaunchAnimator.class)); mStatusBar.mContext = mContext; mStatusBar.mComponents = mContext.getComponents(); mEntryManager.setUpForTest(mStatusBar, mStackScroller, mStatusBar, mHeadsUpManager, @@ -593,7 +595,8 @@ public class StatusBarTest extends SysuiTestCase { VisualStabilityManager visualStabilityManager, NotificationViewHierarchyManager viewHierarchyManager, TestableNotificationEntryManager entryManager, ScrimController scrimController, - FingerprintUnlockController fingerprintUnlockController) { + FingerprintUnlockController fingerprintUnlockController, + ActivityLaunchAnimator launchAnimator) { mStatusBarKeyguardViewManager = man; mUnlockMethodCache = unlock; mKeyguardIndicationController = key; @@ -610,6 +613,7 @@ public class StatusBarTest extends SysuiTestCase { mEntryManager = entryManager; mScrimController = scrimController; mFingerprintUnlockController = fingerprintUnlockController; + mActivityLaunchAnimator = launchAnimator; } private WakefulnessLifecycle createAwakeWakefulnessLifecycle() { diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index bd93b1795ae3..1dd92f3130a7 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -1577,13 +1577,22 @@ public class LocationManagerService extends ILocationManager.Stub { } /** - * Returns all providers by name, including passive, but excluding - * fused, also including ones that are not permitted to - * be accessed by the calling activity or are currently disabled. + * Returns all providers by name, including passive and the ones that are not permitted to + * be accessed by the calling activity or are currently disabled, but excluding fused. */ @Override public List<String> getAllProviders() { - List<String> out = getProviders(null /*criteria*/, false /*enabledOnly*/); + ArrayList<String> out; + synchronized (mLock) { + out = new ArrayList<>(mProviders.size()); + for (LocationProviderInterface provider : mProviders) { + String name = provider.getName(); + if (LocationManager.FUSED_PROVIDER.equals(name)) { + continue; + } + out.add(name); + } + } if (D) Log.d(TAG, "getAllProviders()=" + out); return out; } @@ -2586,9 +2595,10 @@ public class LocationManagerService extends ILocationManager.Stub { // Check INTERACT_ACROSS_USERS permission if userId is not current user id. checkInteractAcrossUsersPermission(userId); - // Enable or disable all location providers + // Enable or disable all location providers. Fused provider and passive provider are + // excluded. synchronized (mLock) { - for(String provider : getAllProviders()) { + for(String provider : getAllProvidersForLocationSettings()) { setProviderEnabledForUser(provider, enabled, userId); } } @@ -2605,9 +2615,10 @@ public class LocationManagerService extends ILocationManager.Stub { // Check INTERACT_ACROSS_USERS permission if userId is not current user id. checkInteractAcrossUsersPermission(userId); - // If at least one location provider is enabled, return true + // If at least one location provider is enabled, return true. Fused provider and passive + // provider are excluded. synchronized (mLock) { - for (String provider : getAllProviders()) { + for (String provider : getAllProvidersForLocationSettings()) { if (isProviderEnabledForUser(provider, userId)) { return true; } @@ -2691,6 +2702,26 @@ public class LocationManagerService extends ILocationManager.Stub { } /** + * Return all location providers except fused provider and passive provider. These two + * providers are not generating location by themselves, but only echo locations from other + * providers. + * + * @return All location providers except fused provider and passive provider, including + * providers that are not permitted to be accessed by the calling activity or are + * currently disabled. + */ + private List<String> getAllProvidersForLocationSettings() { + List<String> providersForSettings = new ArrayList<>(mProviders.size()); + for (String provider : getAllProviders()) { + if (provider.equals(LocationManager.PASSIVE_PROVIDER)) { + continue; + } + providersForSettings.add(provider); + } + return providersForSettings; + } + + /** * Read location provider status from Settings.Secure * * @param provider the location provider to query diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index bedf043147de..edeee3e590ea 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -133,6 +133,7 @@ import com.android.server.pm.UserManagerService; import org.xmlpull.v1.XmlPullParserException; +import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; @@ -4767,6 +4768,16 @@ public class AudioService extends IAudioService.Stub Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode); } + private String getSoundEffectFilePath(int effectType) { + String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH + + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]); + if (!new File(filePath).isFile()) { + filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]); + } + return filePath; + } + private boolean onLoadSoundEffects() { int status; @@ -4836,9 +4847,7 @@ public class AudioService extends IAudioService.Stub continue; } if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) { - String filePath = Environment.getRootDirectory() - + SOUND_EFFECTS_PATH - + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]); + String filePath = getSoundEffectFilePath(effect); int sampleId = mSoundPool.load(filePath, 0); if (sampleId <= 0) { Log.w(TAG, "Soundpool could not load file: "+filePath); @@ -4944,8 +4953,7 @@ public class AudioService extends IAudioService.Stub } else { MediaPlayer mediaPlayer = new MediaPlayer(); try { - String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + - SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]); + String filePath = getSoundEffectFilePath(effectType); mediaPlayer.setDataSource(filePath); mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM); mediaPlayer.prepare(); diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 5bf38dc21305..10e05cf34955 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -362,9 +362,10 @@ public class OtaDexoptService extends IOtaDexopt.Stub { continue; } - // If the path is in /system or /vendor, ignore. It will have been ota-dexopted into - // /data/ota and moved into the dalvik-cache already. - if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")) { + // If the path is in /system, /vendor or /product, ignore. It will have been + // ota-dexopted into /data/ota and moved into the dalvik-cache already. + if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor") + || pkg.codePath.startsWith("/product")) { continue; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 837a118384be..776794593512 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -466,6 +466,7 @@ public class PackageManagerService extends IPackageManager.Stub static final int SCAN_AS_PRIVILEGED = 1<<18; static final int SCAN_AS_OEM = 1<<19; static final int SCAN_AS_VENDOR = 1<<20; + static final int SCAN_AS_PRODUCT = 1<<21; @IntDef(flag = true, prefix = { "SCAN_" }, value = { SCAN_NO_DEX, @@ -570,6 +571,8 @@ public class PackageManagerService extends IPackageManager.Stub private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay"; + private static final String PRODUCT_OVERLAY_DIR = "/product/overlay"; + private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB = "pm.dexopt.priv-apps-oob"; /** Canonical intent used to identify what counts as a "web browser" app */ @@ -2552,7 +2555,7 @@ public class PackageManagerService extends IPackageManager.Stub scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE; } - // Collect vendor overlay packages. (Do this before scanning any apps.) + // Collect vendor/product overlay packages. (Do this before scanning any apps.) // For security and version matching reason, only consider // overlay packages if they reside in the right directory. scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), @@ -2562,6 +2565,13 @@ public class PackageManagerService extends IPackageManager.Stub | SCAN_AS_SYSTEM | SCAN_AS_VENDOR, 0); + scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR), + mDefParseFlags + | PackageParser.PARSE_IS_SYSTEM_DIR, + scanFlags + | SCAN_AS_SYSTEM + | SCAN_AS_PRODUCT, + 0); mParallelPackageParserCallback.findStaticOverlayPackages(); @@ -2595,8 +2605,7 @@ public class PackageManagerService extends IPackageManager.Stub 0); // Collected privileged vendor packages. - File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), - "priv-app"); + File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app"); try { privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile(); } catch (IOException e) { @@ -2636,6 +2645,37 @@ public class PackageManagerService extends IPackageManager.Stub | SCAN_AS_OEM, 0); + // Collected privileged product packages. + File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app"); + try { + privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile(); + } catch (IOException e) { + // failed to look up canonical path, continue with original one + } + scanDirTracedLI(privilegedProductAppDir, + mDefParseFlags + | PackageParser.PARSE_IS_SYSTEM_DIR, + scanFlags + | SCAN_AS_SYSTEM + | SCAN_AS_PRODUCT + | SCAN_AS_PRIVILEGED, + 0); + + // Collect ordinary product packages. + File productAppDir = new File(Environment.getProductDirectory(), "app"); + try { + productAppDir = productAppDir.getCanonicalFile(); + } catch (IOException e) { + // failed to look up canonical path, continue with original one + } + scanDirTracedLI(productAppDir, + mDefParseFlags + | PackageParser.PARSE_IS_SYSTEM_DIR, + scanFlags + | SCAN_AS_SYSTEM + | SCAN_AS_PRODUCT, + 0); + // Prune any system packages that no longer exist. final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>(); // Stub packages must either be replaced with full versions in the /data @@ -2842,6 +2882,23 @@ Slog.e("TODD", scanFlags | SCAN_AS_SYSTEM | SCAN_AS_OEM; + } else if (FileUtils.contains(privilegedProductAppDir, scanFile)) { + reparseFlags = + mDefParseFlags | + PackageParser.PARSE_IS_SYSTEM_DIR; + rescanFlags = + scanFlags + | SCAN_AS_SYSTEM + | SCAN_AS_PRODUCT + | SCAN_AS_PRIVILEGED; + } else if (FileUtils.contains(productAppDir, scanFile)) { + reparseFlags = + mDefParseFlags | + PackageParser.PARSE_IS_SYSTEM_DIR; + rescanFlags = + scanFlags + | SCAN_AS_SYSTEM + | SCAN_AS_PRODUCT; } else { Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile); continue; @@ -9862,6 +9919,7 @@ Slog.e("TODD", * <li>{@link #SCAN_AS_PRIVILEGED}</li> * <li>{@link #SCAN_AS_OEM}</li> * <li>{@link #SCAN_AS_VENDOR}</li> + * <li>{@link #SCAN_AS_PRODUCT}</li> * <li>{@link #SCAN_AS_INSTANT_APP}</li> * <li>{@link #SCAN_AS_VIRTUAL_PRELOAD}</li> * </ul> @@ -9884,6 +9942,10 @@ Slog.e("TODD", & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0) { scanFlags |= SCAN_AS_VENDOR; } + if ((disabledPkgSetting.pkgPrivateFlags + & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) { + scanFlags |= SCAN_AS_PRODUCT; + } } if (pkgSetting != null) { final int userId = ((user == null) ? 0 : user.getIdentifier()); @@ -10662,6 +10724,10 @@ Slog.e("TODD", pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VENDOR; } + if ((scanFlags & SCAN_AS_PRODUCT) != 0) { + pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT; + } + if (!isSystemApp(pkg)) { // Only system apps can use these features. pkg.mOriginalPackages = null; @@ -11708,6 +11774,8 @@ Slog.e("TODD", codeRoot = Environment.getOemDirectory(); } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) { codeRoot = Environment.getVendorDirectory(); + } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) { + codeRoot = Environment.getProductDirectory(); } else { // Unrecognized code path; take its top real segment as the apk root: // e.g. /something/app/blah.apk => /something @@ -16110,7 +16178,7 @@ Slog.e("TODD", boolean sysPkg = (isSystemApp(oldPackage)); if (sysPkg) { - // Set the system/privileged/oem/vendor flags as needed + // Set the system/privileged/oem/vendor/product flags as needed final boolean privileged = (oldPackage.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; @@ -16120,12 +16188,16 @@ Slog.e("TODD", final boolean vendor = (oldPackage.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; + final boolean product = + (oldPackage.applicationInfo.privateFlags + & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0; final @ParseFlags int systemParseFlags = parseFlags; final @ScanFlags int systemScanFlags = scanFlags | SCAN_AS_SYSTEM | (privileged ? SCAN_AS_PRIVILEGED : 0) | (oem ? SCAN_AS_OEM : 0) - | (vendor ? SCAN_AS_VENDOR : 0); + | (vendor ? SCAN_AS_VENDOR : 0) + | (product ? SCAN_AS_PRODUCT : 0); replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags, user, allUsers, installerPackageName, res, installReason); @@ -17373,6 +17445,10 @@ Slog.e("TODD", return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; } + private static boolean isProductApp(PackageParser.Package pkg) { + return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0; + } + private static boolean hasDomainURLs(PackageParser.Package pkg) { return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0; } @@ -18112,8 +18188,10 @@ Slog.e("TODD", try { final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app"); final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app"); + final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app"); return path.startsWith(privilegedAppDir.getCanonicalPath()) - || path.startsWith(privilegedVendorAppDir.getCanonicalPath()); + || path.startsWith(privilegedVendorAppDir.getCanonicalPath()) + || path.startsWith(privilegedProductAppDir.getCanonicalPath()); } catch (IOException e) { Slog.e(TAG, "Unable to access code path " + path); } @@ -18138,6 +18216,15 @@ Slog.e("TODD", return false; } + static boolean locationIsProduct(String path) { + try { + return path.startsWith(Environment.getProductDirectory().getCanonicalPath()); + } catch (IOException e) { + Slog.e(TAG, "Unable to access code path " + path); + } + return false; + } + /* * Tries to delete system package. */ @@ -18262,6 +18349,9 @@ Slog.e("TODD", if (locationIsVendor(codePathString)) { scanFlags |= SCAN_AS_VENDOR; } + if (locationIsProduct(codePathString)) { + scanFlags |= SCAN_AS_PRODUCT; + } final File codePath = new File(codePathString); final PackageParser.Package pkg = diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 47cd81326932..686c4a5eb321 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1555,6 +1555,15 @@ class PackageManagerShellCommand extends ShellCommand { } } + private boolean isProductApp(String pkg) { + try { + final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM); + return info != null && info.applicationInfo.isProduct(); + } catch (RemoteException e) { + return false; + } + } + private int runGetPrivappPermissions() { final String pkg = getNextArg(); if (pkg == null) { @@ -1562,9 +1571,14 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } - ArraySet<String> privAppPermissions = isVendorApp(pkg) ? - SystemConfig.getInstance().getVendorPrivAppPermissions(pkg) - : SystemConfig.getInstance().getPrivAppPermissions(pkg); + ArraySet<String> privAppPermissions = null; + if (isVendorApp(pkg)) { + privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg); + } else if (isProductApp(pkg)) { + privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg); + } else { + privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); + } getOutPrintWriter().println(privAppPermissions == null ? "{}" : privAppPermissions.toString()); @@ -1578,9 +1592,14 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } - ArraySet<String> privAppPermissions = isVendorApp(pkg) ? - SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg) - : SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); + ArraySet<String> privAppPermissions = null; + if (isVendorApp(pkg)) { + privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg); + } else if (isProductApp(pkg)) { + privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg); + } else { + privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); + } getOutPrintWriter().println(privAppPermissions == null ? "{}" : privAppPermissions.toString()); diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 2a2430c07980..3e2bd4a1b3ba 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -173,6 +173,10 @@ public final class PackageSetting extends PackageSettingBase { return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; } + public boolean isProduct() { + return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0; + } + public boolean isForwardLocked() { return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0; } diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java index 46ba0060d93e..7c92045c7c5e 100644 --- a/services/core/java/com/android/server/pm/SettingBase.java +++ b/services/core/java/com/android/server/pm/SettingBase.java @@ -62,6 +62,7 @@ abstract class SettingBase { & (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED | ApplicationInfo.PRIVATE_FLAG_OEM | ApplicationInfo.PRIVATE_FLAG_VENDOR + | ApplicationInfo.PRIVATE_FLAG_PRODUCT | ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER); } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 8ce412e5783a..5e9019dfea04 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -851,6 +851,8 @@ public final class Settings { pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM; pkgSetting.pkgPrivateFlags |= pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR; + pkgSetting.pkgPrivateFlags |= + pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT; pkgSetting.primaryCpuAbiString = primaryCpuAbi; pkgSetting.secondaryCpuAbiString = secondaryCpuAbi; if (childPkgNames != null) { @@ -4397,6 +4399,7 @@ public final class Settings { ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER", ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY", ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR", + ApplicationInfo.PRIVATE_FLAG_PRODUCT, "PRODUCT", ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD", }; diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index 6e07eaac9c44..e2123c25dd81 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -1215,6 +1215,10 @@ public final class DefaultPermissionGrantPolicy { if (dir.isDirectory() && dir.canRead()) { Collections.addAll(ret, dir.listFiles()); } + dir = new File(Environment.getProductDirectory(), "etc/default-permissions"); + if (dir.isDirectory() && dir.canRead()) { + Collections.addAll(ret, dir.listFiles()); + } return ret.isEmpty() ? null : ret.toArray(new File[0]); } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 786b998862de..cb3b1073a593 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -954,9 +954,16 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages)); * <p>This handles parent/child apps. */ private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) { - ArraySet<String> wlPermissions = pkg.isVendor() ? - SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName) - : SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName); + ArraySet<String> wlPermissions = null; + if (pkg.isVendor()) { + wlPermissions = + SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName); + } else if (pkg.isProduct()) { + wlPermissions = + SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName); + } else { + wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName); + } // Let's check if this package is whitelisted... boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm); // If it's not, we'll also tail-recurse to the parent. @@ -979,11 +986,17 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages)); // Only report violations for apps on system image if (!mSystemReady && !pkg.isUpdatedSystemApp()) { // it's only a reportable violation if the permission isn't explicitly denied - final ArraySet<String> deniedPermissions = pkg.isVendor() ? - SystemConfig.getInstance() - .getVendorPrivAppDenyPermissions(pkg.packageName) - : SystemConfig.getInstance() - .getPrivAppDenyPermissions(pkg.packageName); + ArraySet<String> deniedPermissions = null; + if (pkg.isVendor()) { + deniedPermissions = SystemConfig.getInstance() + .getVendorPrivAppDenyPermissions(pkg.packageName); + } else if (pkg.isProduct()) { + deniedPermissions = SystemConfig.getInstance() + .getProductPrivAppDenyPermissions(pkg.packageName); + } else { + deniedPermissions = SystemConfig.getInstance() + .getPrivAppDenyPermissions(pkg.packageName); + } final boolean permissionViolation = deniedPermissions == null || !deniedPermissions.contains(perm); if (permissionViolation) { diff --git a/tests/libs-permissions/Android.mk b/tests/libs-permissions/Android.mk new file mode 100644 index 000000000000..eb3862390338 --- /dev/null +++ b/tests/libs-permissions/Android.mk @@ -0,0 +1,15 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := com.android.test.libs.product +LOCAL_PRODUCT_MODULE := true +LOCAL_SRC_FILES := $(call all-java-files-under, product/java) +LOCAL_REQUIRED_MODULES := com.android.test.libs.product.xml +include $(BUILD_JAVA_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := com.android.test.libs.product.xml +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions +LOCAL_SRC_FILES:= product/com.android.test.libs.product.xml +include $(BUILD_PREBUILT) diff --git a/tests/libs-permissions/product/com.android.test.libs.product.xml b/tests/libs-permissions/product/com.android.test.libs.product.xml new file mode 100644 index 000000000000..0a955e9df7fd --- /dev/null +++ b/tests/libs-permissions/product/com.android.test.libs.product.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<permissions> + <library name="com.android.test.libs.product" + file="/product/framework/com.android.test.libs.product.jar" /> +</permissions> diff --git a/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java b/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java new file mode 100644 index 000000000000..f49b46e72c25 --- /dev/null +++ b/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.libs.product; + +/** + * Test class for product libs. + */ +public class LibsProductTest { + + /** + * Dummpy method for testing. + */ + public static void test() { + } +} diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk index b001c8c466a9..3c80ad8587af 100644 --- a/tests/privapp-permissions/Android.mk +++ b/tests/privapp-permissions/Android.mk @@ -29,3 +29,17 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/permissions LOCAL_SRC_FILES:= vendor/privapp-permissions-test.xml include $(BUILD_PREBUILT) +include $(CLEAR_VARS) +LOCAL_PACKAGE_NAME := ProductPrivAppPermissionTest +LOCAL_PRIVILEGED_MODULE := true +LOCAL_MANIFEST_FILE := product/AndroidManifest.xml +LOCAL_PRODUCT_MODULE := true +LOCAL_REQUIRED_MODULES := productprivapp-permissions-test.xml +include $(BUILD_PACKAGE) + +include $(CLEAR_VARS) +LOCAL_MODULE := productprivapp-permissions-test.xml +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions +LOCAL_SRC_FILES:= product/privapp-permissions-test.xml +include $(BUILD_PREBUILT) diff --git a/tests/privapp-permissions/product/AndroidManifest.xml b/tests/privapp-permissions/product/AndroidManifest.xml new file mode 100644 index 000000000000..3d9415c3df41 --- /dev/null +++ b/tests/privapp-permissions/product/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright (C) 2018 Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.framework.permission.privapp.tests.product"> + + <!-- MANAGE_USB is signature|privileged --> + <uses-permission android:name="android.permission.MANAGE_USB"/> +</manifest> diff --git a/tests/privapp-permissions/product/privapp-permissions-test.xml b/tests/privapp-permissions/product/privapp-permissions-test.xml new file mode 100644 index 000000000000..f298f9da41b7 --- /dev/null +++ b/tests/privapp-permissions/product/privapp-permissions-test.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<permissions> + <privapp-permissions package="com.android.framework.permission.privapp.tests.product"> + <permission name="android.permission.MANAGE_USB"/> + </privapp-permissions> +</permissions> diff --git a/tools/incident_report/main.cpp b/tools/incident_report/main.cpp index bd1b973c7bdf..302d7395f3e4 100644 --- a/tools/incident_report/main.cpp +++ b/tools/incident_report/main.cpp @@ -452,9 +452,10 @@ main(int argc, char** argv) bool adbIncidentWorkaround = true; pid_t childPid = -1; vector<string> sections; + const char* privacy = NULL; int opt; - while ((opt = getopt(argc, argv, "bhi:o:s:tw")) != -1) { + while ((opt = getopt(argc, argv, "bhi:o:s:twp:")) != -1) { switch (opt) { case 'b': outputFormat = OUTPUT_PROTO; @@ -477,6 +478,9 @@ main(int argc, char** argv) case 'w': adbIncidentWorkaround = false; break; + case 'p': + privacy = optarg; + break; default: usage(stderr); return 1; @@ -526,7 +530,7 @@ main(int argc, char** argv) } // TODO: This is what the real implementation will be... - char const** args = (char const**)malloc(sizeof(char*) * (6 + sections.size())); + char const** args = (char const**)malloc(sizeof(char*) * (8 + sections.size())); int argpos = 0; args[argpos++] = "adb"; if (adbSerial != NULL) { @@ -535,6 +539,10 @@ main(int argc, char** argv) } args[argpos++] = "shell"; args[argpos++] = "incident"; + if (privacy != NULL) { + args[argpos++] = "-p"; + args[argpos++] = privacy; + } for (vector<string>::const_iterator it=sections.begin(); it!=sections.end(); it++) { args[argpos++] = it->c_str(); } |