diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java index 606f0df0dfda..7c5f7ea9746b 100644 --- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java +++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java @@ -1165,6 +1165,9 @@ public boolean areAlarmsRestricted(int uid, @NonNull String packageName) { return false; } synchronized (mLock) { + if (isAppRestricted(uid, packageName)) { + return true; + } final int appId = UserHandle.getAppId(uid); if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) { return false; @@ -1210,6 +1213,9 @@ public boolean areJobsRestricted(int uid, @NonNull String packageName, return false; } synchronized (mLock) { + if (isAppRestricted(uid, packageName)) { + return true; + } final int appId = UserHandle.getAppId(uid); if (ArrayUtils.contains(mPowerExemptAllAppIds, appId) || ArrayUtils.contains(mTempExemptAppIds, appId)) { @@ -1332,6 +1338,15 @@ public boolean isUidTempPowerSaveExempt(int uid) { } } + /** + * @return whether the app is restricted battery usage + */ + public boolean isAppRestricted(int uid, String packageName) { + return mAppOpsManager.checkOpNoThrow( + AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, + uid, packageName) != AppOpsManager.MODE_ALLOWED; + } + /** * Dump the internal state to the given PrintWriter. Can be included in the dump * of a binder service to be output on the shell command "dumpsys". diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java index b27ff411dd58..5e534c85b68e 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java @@ -1797,7 +1797,7 @@ private void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets // shouldn't be surprising. // Exclude REASON_SUB_FORCED_USER_FLAG_INTERACTION since the RESTRICTED bucket // isn't directly visible in that flow. - if (Build.IS_DEBUGGABLE + if (Build.IS_ENG && (reason & REASON_SUB_MASK) != REASON_SUB_FORCED_USER_FLAG_INTERACTION) { Toast.makeText(mContext, diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 9284ed8e11ca..f9e329a41c15 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -67,7 +67,6 @@ namespace android { using ui::DisplayMode; static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip"; -static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "/product/media/bootanimation-dark.zip"; static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip"; static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip"; static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip"; @@ -107,6 +106,7 @@ static const char PROGRESS_PROP_NAME[] = "service.bootanim.progress"; static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays"; static const char CLOCK_ENABLED_PROP_NAME[] = "persist.sys.bootanim.clock.enabled"; static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; +static const int MAX_CHECK_EXIT_INTERVAL_US = 50000; static constexpr size_t TEXT_POS_LEN_MAX = 16; static const int DYNAMIC_COLOR_COUNT = 4; static const char U_TEXTURE[] = "uTexture"; @@ -741,9 +741,8 @@ void BootAnimation::findBootAnimationFile() { } } - const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1; static const std::vector bootFiles = { - APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE, + APEX_BOOTANIMATION_FILE, PRODUCT_BOOTANIMATION_FILE, OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE }; static const std::vector shutdownFiles = { @@ -1691,7 +1690,17 @@ bool BootAnimation::playAnimation(const Animation& animation) { checkExit(); } - usleep(part.pause * ns2us(frameDuration)); + int pauseDuration = part.pause * ns2us(frameDuration); + while(pauseDuration > 0 && !exitPending()){ + if (pauseDuration > MAX_CHECK_EXIT_INTERVAL_US) { + usleep(MAX_CHECK_EXIT_INTERVAL_US); + pauseDuration -= MAX_CHECK_EXIT_INTERVAL_US; + } else { + usleep(pauseDuration); + break; + } + checkExit(); + } if (exitPending() && !part.count && mCurrentInset >= mTargetInset && !part.hasFadingPhase()) { diff --git a/core/api/current.txt b/core/api/current.txt index 487e57d114c9..c762c207ad79 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -87,6 +87,7 @@ package android { field public static final String DUMP = "android.permission.DUMP"; field public static final String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR"; field public static final String FACTORY_TEST = "android.permission.FACTORY_TEST"; + field public static final String FAKE_PACKAGE_SIGNATURE = "android.permission.FAKE_PACKAGE_SIGNATURE"; field public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE"; field public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"; field public static final String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED"; @@ -222,6 +223,7 @@ package android { field public static final String CALL_LOG = "android.permission-group.CALL_LOG"; field public static final String CAMERA = "android.permission-group.CAMERA"; field public static final String CONTACTS = "android.permission-group.CONTACTS"; + field public static final String FAKE_PACKAGE_SIGNATURE = "android.permission-group.FAKE_PACKAGE_SIGNATURE"; field public static final String LOCATION = "android.permission-group.LOCATION"; field public static final String MICROPHONE = "android.permission-group.MICROPHONE"; field public static final String NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES"; diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 03a97ba1d977..02ee45fde88d 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -5954,6 +5954,12 @@ public void startActivity(Intent intent) { */ @Override public void startActivity(Intent intent, @Nullable Bundle options) { + if (intent != null && intent.getComponent() != null){ + if (intent.getComponent().flattenToString().equals("com.google.android.permissioncontroller/com.android.permissioncontroller.permission.ui.ManagePermissionsActivity")){ + intent = intent.setComponent( + ComponentName.unflattenFromString("com.android.permissioncontroller/com.android.permissioncontroller.permission.ui.ManagePermissionsActivity")); + } + } getAutofillClientController().onStartActivity(intent, mIntent); if (options != null) { startActivityForResult(intent, -1, options); diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index c95a7deba61f..3002fa0650b7 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -691,6 +691,9 @@ public abstract PendingIntent getPendingIntentActivityAsApp( */ public abstract @TempAllowListType int getPushMessagingOverQuotaBehavior(); + // Starts a process as empty. + public abstract int startActivityAsUserEmpty(Bundle options); + /** * Return the startForeground() grace period after calling startForegroundService(). */ diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 5985d6e93107..e37098a0f418 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -160,6 +160,7 @@ import android.telephony.TelephonyFrameworkInitializer; import android.util.AndroidRuntimeException; import android.util.ArrayMap; +import android.util.BoostFramework; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -3427,8 +3428,13 @@ public void updateProcessState(int processState, boolean fromIpc) { if (mLastProcessState == processState) { return; } + // Do not issue a transitional GC if we are transitioning between 2 cached states. + // Only update if the state flips between cached and uncached or vice versa + if (ActivityManager.isProcStateCached(mLastProcessState) + != ActivityManager.isProcStateCached(processState)) { + updateVmProcessState(processState); + } mLastProcessState = processState; - updateVmProcessState(processState); if (localLOGV) { Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState + (fromIpc ? " (from ipc" : "")); @@ -3437,12 +3443,16 @@ public void updateProcessState(int processState, boolean fromIpc) { } /** Update VM state based on ActivityManager.PROCESS_STATE_* constants. */ + // Currently ART VM only uses state updates for Transitional GC, and thus + // this function initiates a Transitional GC for transitions into Cached apps states. private void updateVmProcessState(int processState) { - // TODO: Tune this since things like gmail sync are important background but not jank - // perceptible. - final int state = processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND - ? VM_PROCESS_STATE_JANK_PERCEPTIBLE - : VM_PROCESS_STATE_JANK_IMPERCEPTIBLE; + // Only a transition into Cached state should result in a Transitional GC request + // to the ART runtime. Update VM state to JANK_IMPERCEPTIBLE in that case. + // Note that there are 4 possible cached states currently, all of which are + // JANK_IMPERCEPTIBLE from GC point of view. + final int state = ActivityManager.isProcStateCached(processState) + ? VM_PROCESS_STATE_JANK_IMPERCEPTIBLE + : VM_PROCESS_STATE_JANK_PERCEPTIBLE; VMRuntime.getRuntime().updateProcessState(state); } @@ -6494,6 +6504,8 @@ private String getInstrumentationLibrary(ApplicationInfo appInfo, Instrumentatio @UnsupportedAppUsage private void handleBindApplication(AppBindData data) { + long st_bindApp = SystemClock.uptimeMillis(); + BoostFramework ux_perf = null; // Register the UI Thread as a sensitive thread to the runtime. VMRuntime.registerSensitiveThread(); // In the case the stack depth property exists, pass it down to the runtime. @@ -6612,10 +6624,17 @@ private void handleBindApplication(AppBindData data) { /** * Switch this process to density compatibility mode if needed. */ - if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) + if ((data.appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); + } else { + int overrideDensity = data.appInfo.getOverrideDensity(); + if(overrideDensity != 0) { + Log.d(TAG, "override app density from " + DisplayMetrics.DENSITY_DEVICE + " to " + overrideDensity); + mDensityCompatMode = true; + Bitmap.setDefaultDensity(overrideDensity); + } } mConfigurationController.updateDefaultDensity(data.config.densityDpi); @@ -6713,6 +6732,15 @@ private void handleBindApplication(AppBindData data) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } + if (!Process.isIsolated()) { + final int old_mask = StrictMode.allowThreadDiskWritesMask(); + try { + ux_perf = new BoostFramework(appContext); + } finally { + StrictMode.setThreadPolicyMask(old_mask); + } + } + if (!Process.isIsolated()) { final int oldMask = StrictMode.allowThreadDiskWritesMask(); try { @@ -6839,6 +6867,33 @@ private void handleBindApplication(AppBindData data) { throw e.rethrowFromSystemServer(); } } + long end_bindApp = SystemClock.uptimeMillis(); + int bindApp_dur = (int) (end_bindApp - st_bindApp); + String pkg_name = null; + if (appContext != null) { + pkg_name = appContext.getPackageName(); + } + if (ux_perf != null && !Process.isIsolated() && pkg_name != null) { + String pkgDir = null; + try + { + String codePath = appContext.getPackageCodePath(); + pkgDir = codePath.substring(0, codePath.lastIndexOf('/')); + } + catch(Exception e) + { + Slog.e(TAG, "HeavyGameThread () : Exception_1 = " + e); + } + if (ux_perf.board_first_api_lvl < BoostFramework.VENDOR_T_API_LEVEL && + ux_perf.board_api_lvl < BoostFramework.VENDOR_T_API_LEVEL) { + ux_perf.perfUXEngine_events(BoostFramework.UXE_EVENT_BINDAPP, 0, + pkg_name, + bindApp_dur, + pkgDir); + } else { + ux_perf.perfEvent(BoostFramework.VENDOR_HINT_BINDAPP, pkg_name, 2, bindApp_dur, 0); + } + } } private void handleSetContentCaptureOptionsCallback(String packageName) { @@ -7082,11 +7137,6 @@ public final IContentProvider acquireProvider( } } if (holder == null) { - if (UserManager.get(c).isUserUnlocked(userId)) { - Slog.e(TAG, "Failed to find provider info for " + auth); - } else { - Slog.w(TAG, "Failed to find provider info for " + auth + " (user not unlocked)"); - } return null; } diff --git a/core/java/android/app/AppLockData.aidl b/core/java/android/app/AppLockData.aidl new file mode 100644 index 000000000000..073d1efd2505 --- /dev/null +++ b/core/java/android/app/AppLockData.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2022 FlamingoOS 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 android.app; + +parcelable AppLockData; \ No newline at end of file diff --git a/core/java/android/app/AppLockData.java b/core/java/android/app/AppLockData.java new file mode 100644 index 000000000000..cb3352575c9c --- /dev/null +++ b/core/java/android/app/AppLockData.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2022 FlamingoOS 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 android.app; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Class to hold package level information about an + * application for app lock. + * + * @hide + */ +public final class AppLockData implements Parcelable { + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + + @Override + public AppLockData createFromParcel(Parcel in) { + return new AppLockData(in); + } + + @Override + public AppLockData[] newArray(int size) { + return new AppLockData[size]; + } + }; + + private final String mPackageName; + private final boolean mShouldProtectApp; + private final boolean mShouldRedactNotification; + private final boolean mHideFromLauncher; + + /** @hide */ + public AppLockData( + @NonNull final String packageName, + final boolean shouldProtectApp, + final boolean shouldRedactNotification, + final boolean hideFromLauncher + ) { + mPackageName = packageName; + mShouldProtectApp = shouldProtectApp; + mShouldRedactNotification = shouldRedactNotification; + mHideFromLauncher = hideFromLauncher; + } + + private AppLockData(final Parcel in) { + mPackageName = in.readString(); + mShouldProtectApp = in.readBoolean(); + mShouldRedactNotification = in.readBoolean(); + mHideFromLauncher = in.readBoolean(); + } + + @NonNull + public String getPackageName() { + return mPackageName; + } + + public boolean getShouldProtectApp() { + return mShouldProtectApp; + } + + public boolean getShouldRedactNotification() { + return mShouldRedactNotification; + } + + public boolean getHideFromLauncher() { + return mHideFromLauncher; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(final Parcel parcel, final int flags) { + parcel.writeString(mPackageName); + parcel.writeBoolean(mShouldProtectApp); + parcel.writeBoolean(mShouldRedactNotification); + parcel.writeBoolean(mHideFromLauncher); + } + + @Override + @NonNull + public String toString() { + return "AppLockData[ packageName = " + mPackageName + + ", shouldProtectApp = " + mShouldProtectApp + + ", shouldRedactNotification = " + mShouldRedactNotification + + ", hideFromLauncher = " + mHideFromLauncher + " ]"; + } +} diff --git a/core/java/android/app/AppLockManager.java b/core/java/android/app/AppLockManager.java new file mode 100644 index 000000000000..2fecb7260380 --- /dev/null +++ b/core/java/android/app/AppLockManager.java @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2022 FlamingoOS 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 android.app; + +import android.Manifest; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.annotation.SystemService; +import android.annotation.RequiresPermission; +import android.annotation.UserHandleAware; +import android.content.Context; +import android.os.RemoteException; + +import java.util.List; + +/** + * @hide + */ +@SystemService(Context.APP_LOCK_SERVICE) +public final class AppLockManager { + + /** @hide */ + public static final long DEFAULT_TIMEOUT = 10 * 1000; + + /** @hide */ + public static final boolean DEFAULT_BIOMETRICS_ALLOWED = true; + + /** @hide */ + public static final boolean DEFAULT_PROTECT_APP = false; + + /** @hide */ + public static final boolean DEFAULT_REDACT_NOTIFICATION = false; + + /** @hide */ + public static final boolean DEFAULT_HIDE_IN_LAUNCHER = false; + + /** + * Intent action for starting credential activity in SystemUI. + * @hide + */ + public static final String ACTION_UNLOCK_APP = "android.app.action.UNLOCK_APP"; + + /** + * Intent extra to indicate whether usage of biometrics is allowed. + * @hide + */ + public static final String EXTRA_ALLOW_BIOMETRICS = "android.app.AppLockManager.ALLOW_BIOMETRICS"; + + /** + * Intent extra for the name of the application to unlock. + * @hide + */ + public static final String EXTRA_PACKAGE_LABEL = "android.app.AppLockManager.PACKAGE_LABEL"; + + private final Context mContext; + private final IAppLockManagerService mService; + + /** @hide */ + AppLockManager(Context context, IAppLockManagerService service) { + mContext = context; + mService = service; + } + + /** + * Set whether app should be protected by app lock + * in locked state. Caller must hold {@link android.permission.MANAGE_APP_LOCK}. + * + * @param packageName the package name. + * @param shouldProtectApp true to hide notification content. + * @hide + */ + @UserHandleAware + @RequiresPermission(Manifest.permission.MANAGE_APP_LOCK) + public void setShouldProtectApp(@NonNull String packageName, boolean shouldProtectApp) { + try { + mService.setShouldProtectApp(packageName, shouldProtectApp, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get the current auto lock timeout. + * + * @param userId the user id given by the caller. + * @return the timeout in milliseconds if configuration for + * current user exists, -1 otherwise. + * @hide + */ + @UserHandleAware + public long getTimeout() { + try { + return mService.getTimeout(mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set auto lock timeout. + * Caller must hold {@link android.permission.MANAGE_APP_LOCK}. + * + * @param timeout the timeout in milliseconds. Must be >= 5. + * @param userId the user id given by the caller. + * @hide + */ + @UserHandleAware + @RequiresPermission(Manifest.permission.MANAGE_APP_LOCK) + public void setTimeout(long timeout) { + try { + mService.setTimeout(timeout, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get all the packages protected with app lock. + * Caller must hold {@link android.permission.MANAGE_APP_LOCK}. + * + * @return a unique list of {@link AppLockData} of the protected apps. + * @hide + */ + @UserHandleAware + @NonNull + @RequiresPermission(Manifest.permission.MANAGE_APP_LOCK) + public List getPackageData() { + try { + return mService.getPackageData(mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set whether notification content should be redacted for a package + * in locked state. Caller must hold {@link android.permission.MANAGE_APP_LOCK}. + * + * @param packageName the package name. + * @param shouldRedactNotification true to hide notification content. + * @hide + */ + @UserHandleAware + @RequiresPermission(Manifest.permission.MANAGE_APP_LOCK) + public void setShouldRedactNotification(@NonNull String packageName, boolean shouldRedactNotification) { + try { + mService.setShouldRedactNotification(packageName, shouldRedactNotification, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set whether to allow unlocking with biometrics. + * Caller must hold {@link android.permission.MANAGE_APP_LOCK}. + * + * @param biometricsAllowed whether to use biometrics. + * @hide + */ + @UserHandleAware + @RequiresPermission(Manifest.permission.MANAGE_APP_LOCK) + public void setBiometricsAllowed(boolean biometricsAllowed) { + try { + mService.setBiometricsAllowed(biometricsAllowed, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Check whether biometrics is allowed for unlocking. + * + * @return true if biometrics will be used for unlocking, false otherwise. + * @hide + */ + @UserHandleAware + public boolean isBiometricsAllowed() { + try { + return mService.isBiometricsAllowed(mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Unlock a package following authentication with credentials. + * Caller must hold {@link android.permission.MANAGE_APP_LOCK}. + * + * @param packageName the name of the package to unlock. + * @hide + */ + @UserHandleAware + @RequiresPermission(Manifest.permission.MANAGE_APP_LOCK) + public void unlockPackage(@NonNull String packageName) { + try { + mService.unlockPackage(packageName, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Hide or unhide an application from launcher. + * Caller must hold {@link android.permission.MANAGE_APP_LOCK}. + * + * @param packageName the name of the package to hide or unhide. + * @param hide whether to hide or not. + * @hide + */ + @UserHandleAware + @RequiresPermission(Manifest.permission.MANAGE_APP_LOCK) + public void setPackageHidden(@NonNull String packageName, boolean hide) { + try { + mService.setPackageHidden(packageName, hide, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get the list of applications hidden from launcher. + * Caller must hold {@link android.permission.MANAGE_APP_LOCK}. + * + * @return list of package names of the hidden apps. + * @hide + */ + @UserHandleAware + @RequiresPermission(Manifest.permission.MANAGE_APP_LOCK) + @NonNull + public List getHiddenPackages() { + try { + return mService.getHiddenPackages(mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Check whether package is protected by app lock + * + * @return true if package is protected by app lock, false otherwise. + * @hide + */ + @UserHandleAware + public boolean isPackageProtected(@NonNull String packageName) { + try { + return mService.isPackageProtected(packageName, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Check whether package is hidden by app lock + * + * @return true if package is hidden by app lock, false otherwise. + * @hide + */ + @UserHandleAware + public boolean isPackageHidden(@NonNull String packageName) { + try { + return mService.isPackageHidden(packageName, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 475e0f4cb05b..a261c459f97c 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -818,8 +818,64 @@ public Boolean recompute(HasSystemFeatureQuery query) { } }; + private static final String[] pTensorCodenames = { + "felix", + "tangorpro", + "lynx", + "cheetah", + "panther", + "bluejay", + "oriole", + "raven" + }; + + private static final String[] featuresPixel = { + "com.google.android.apps.photos.PIXEL_2019_PRELOAD", + "com.google.android.apps.photos.PIXEL_2019_MIDYEAR_PRELOAD", + "com.google.android.apps.photos.PIXEL_2018_PRELOAD", + "com.google.android.apps.photos.PIXEL_2017_PRELOAD", + "com.google.android.feature.PIXEL_2021_MIDYEAR_EXPERIENCE", + "com.google.android.feature.PIXEL_2020_EXPERIENCE", + "com.google.android.feature.PIXEL_2020_MIDYEAR_EXPERIENCE", + "com.google.android.feature.PIXEL_2019_EXPERIENCE", + "com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE", + "com.google.android.feature.PIXEL_2018_EXPERIENCE", + "com.google.android.feature.PIXEL_2017_EXPERIENCE", + "com.google.android.feature.PIXEL_EXPERIENCE", + "com.google.android.feature.GOOGLE_BUILD", + "com.google.android.feature.GOOGLE_EXPERIENCE" + }; + + private static final String[] featuresTensor = { + "com.google.android.feature.PIXEL_2022_EXPERIENCE", + "com.google.android.feature.PIXEL_2022_MIDYEAR_EXPERIENCE", + "com.google.android.feature.PIXEL_2021_EXPERIENCE", + }; + + private static final String[] featuresNexus = { + "com.google.android.apps.photos.NEXUS_PRELOAD", + "com.google.android.apps.photos.nexus_preload" + }; + @Override public boolean hasSystemFeature(String name, int version) { + String packageName = ActivityThread.currentPackageName(); + boolean isTensorDevice = Arrays.asList(pTensorCodenames).contains(SystemProperties.get("ro.product.device")); + if (packageName != null && packageName.equals("com.google.android.apps.photos")) { + if (Arrays.asList(featuresPixel).contains(name)) return false; + if (Arrays.asList(featuresTensor).contains(name)) return false; + if (Arrays.asList(featuresNexus).contains(name)) return true; + } + if (Arrays.asList(featuresPixel).contains(name)) return true; + if (Arrays.asList(featuresTensor).contains(name) && !isTensorDevice) { + return false; + } else if (packageName != null && + (packageName.contains("com.google.android.apps.nexuslauncher") || + packageName.contains("com.google.android.apps.recorder")) && + Arrays.asList(featuresTensor).contains(name) && !isTensorDevice) { + return false; + } + return mHasSystemFeatureCache.query(new HasSystemFeatureQuery(name, version)); } diff --git a/core/java/android/app/ConfigurationController.java b/core/java/android/app/ConfigurationController.java index 18dc1ce18baf..3ff0da8f7ea4 100644 --- a/core/java/android/app/ConfigurationController.java +++ b/core/java/android/app/ConfigurationController.java @@ -28,6 +28,9 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.HardwareRenderer; +import android.graphics.Typeface; +import android.inputmethodservice.InputMethodService; +import android.os.Build; import android.os.LocaleList; import android.os.Trace; import android.util.DisplayMetrics; @@ -180,6 +183,7 @@ void handleConfigurationChanged(@Nullable Configuration config, final Application app = mActivityThread.getApplication(); final Resources appResources = app.getResources(); mResourcesManager.applyConfigurationToResources(config, compat); + Typeface.updateDefaultFont(appResources); updateLocaleListFromAppContext(app.getApplicationContext()); if (mConfiguration == null) { diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 8367441b1b95..69e6323e3422 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -760,4 +760,14 @@ interface IActivityManager { *

*/ int getBackgroundRestrictionExemptionReason(int uid); + + /** + * Should disable touch if three fingers to screen shot is active? + */ + boolean isSwipeToScreenshotGestureActive(); + + /** + * Force full screen for devices with cutout + */ + boolean shouldForceCutoutFullscreen(in String packageName); } diff --git a/core/java/android/app/IAppLockManagerService.aidl b/core/java/android/app/IAppLockManagerService.aidl new file mode 100644 index 000000000000..6e14f4c86f17 --- /dev/null +++ b/core/java/android/app/IAppLockManagerService.aidl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 FlamingoOS 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 android.app; + +import android.app.AppLockData; + +/** + * Interface for managing app lock. + * @hide + */ +interface IAppLockManagerService { + + void setShouldProtectApp(in String packageName, in boolean secure, in int userId); + + long getTimeout(in int userId); + + void setTimeout(in long timeout, in int userId); + + List getPackageData(in int userId); + + void setShouldRedactNotification(in String packageName, in boolean secure, in int userId); + + void setBiometricsAllowed(in boolean biometricsAllowed, in int userId); + + boolean isBiometricsAllowed(in int userId); + + void unlockPackage(in String packageName, in int userId); + + void setPackageHidden(in String packageName, boolean hide, in int userId); + + List getHiddenPackages(in int userId); + + boolean isPackageProtected(in String packageName, in int userId); + + boolean isPackageHidden(in String packageName, in int userId); +} diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 556058b567f9..f9c9f0d77fe0 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -64,6 +64,8 @@ import java.util.List; import java.util.concurrent.TimeoutException; +import com.android.internal.util.custom.PixelPropsUtils; + /** * Base class for implementing application instrumentation code. When running * with instrumentation turned on, this class will be instantiated for you @@ -1242,6 +1244,8 @@ public Application newApplication(ClassLoader cl, String className, Context cont Application app = getFactory(context.getPackageName()) .instantiateApplication(cl, className); app.attach(context); + String packageName = context.getPackageName(); + PixelPropsUtils.setProps(packageName); return app; } @@ -1259,6 +1263,8 @@ static public Application newApplication(Class clazz, Context context) ClassNotFoundException { Application app = (Application)clazz.newInstance(); app.attach(context); + String packageName = context.getPackageName(); + PixelPropsUtils.setProps(packageName); return app; } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index ec100c2fa0c0..40d9bed4b125 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -213,7 +213,6 @@ import android.telephony.TelephonyFrameworkInitializer; import android.telephony.TelephonyRegistryManager; import android.transparency.BinaryTransparencyManager; -import android.util.ArrayMap; import android.util.Log; import android.util.Slog; import android.uwb.UwbFrameworkInitializer; @@ -246,6 +245,7 @@ import com.android.internal.policy.PhoneLayoutInflater; import com.android.internal.util.Preconditions; +import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -265,10 +265,10 @@ public final class SystemServiceRegistry { // Service registry information. // This information is never changed once static initialization has completed. private static final Map, String> SYSTEM_SERVICE_NAMES = - new ArrayMap, String>(); + new HashMap, String>(); private static final Map> SYSTEM_SERVICE_FETCHERS = - new ArrayMap>(); - private static final Map SYSTEM_SERVICE_CLASS_NAMES = new ArrayMap<>(); + new HashMap>(); + private static final Map SYSTEM_SERVICE_CLASS_NAMES = new HashMap<>(); private static int sServiceCacheSize; @@ -1037,9 +1037,10 @@ public MediaProjectionManager createService(ContextImpl ctx) { registerService(Context.APPWIDGET_SERVICE, AppWidgetManager.class, new CachedServiceFetcher() { @Override - public AppWidgetManager createService(ContextImpl ctx) throws ServiceNotFoundException { - IBinder b = ServiceManager.getServiceOrThrow(Context.APPWIDGET_SERVICE); - return new AppWidgetManager(ctx, IAppWidgetService.Stub.asInterface(b)); + public AppWidgetManager createService(ContextImpl ctx) { + IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); + return b == null ? null : new AppWidgetManager(ctx, + IAppWidgetService.Stub.asInterface(b)); }}); registerService(Context.MIDI_SERVICE, MidiManager.class, @@ -1522,6 +1523,17 @@ public AmbientContextManager createService(ContextImpl ctx) return new AmbientContextManager(ctx.getOuterContext(), manager); }}); + registerService(Context.APP_LOCK_SERVICE, AppLockManager.class, + new CachedServiceFetcher() { + @Override + public AppLockManager createService(ContextImpl ctx) + throws ServiceNotFoundException { + IBinder binder = ServiceManager.getServiceOrThrow( + Context.APP_LOCK_SERVICE); + return new AppLockManager(ctx, + IAppLockManagerService.Stub.asInterface(binder)); + }}); + sInitializing = true; try { // Note: the following functions need to be @SystemApis, once they become mainline diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 77ca48a8ed1d..37ed62b59d4b 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -38,6 +38,7 @@ import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; +import android.app.AppLockManager; import android.app.BroadcastOptions; import android.app.GameManager; import android.app.IApplicationThread; @@ -6019,6 +6020,14 @@ public abstract boolean startInstrumentation(@NonNull ComponentName className, */ public static final String DISPLAY_HASH_SERVICE = "display_hash"; + /** + * {@link AppLockManager}. + * + * @see #getSystemService(String) + * @hide + */ + public static final String APP_LOCK_SERVICE = "app_lock"; + /** * Use with {@link #getSystemService(String)} to retrieve a * {@link android.app.LocaleManager}. diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 24c383692c09..ec22ae86d0ee 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -30,6 +30,8 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Environment; +import android.os.SystemProperties; +import android.util.DisplayMetrics; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -867,6 +869,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public static final String METADATA_PRELOADED_FONTS = "preloaded_fonts"; + /** + * Boolean indicating whether the resolution of the SurfaceView associated + * with this appplication can be overriden. + * {@hide} + */ + public int overrideRes = 0; + + /** + * In case, app needs different density than device density, set this value. + * {@hide} + */ + public int overrideDensity = 0; + /** * The required smallest screen width the application can run on. If 0, * nothing has been specified. Comes from @@ -1880,6 +1895,8 @@ public ApplicationInfo(ApplicationInfo orig) { flags = orig.flags; privateFlags = orig.privateFlags; privateFlagsExt = orig.privateFlagsExt; + overrideRes = orig.overrideRes; + overrideDensity = orig.overrideDensity; requiresSmallestWidthDp = orig.requiresSmallestWidthDp; compatibleWidthLimitDp = orig.compatibleWidthLimitDp; largestWidthLimitDp = orig.largestWidthLimitDp; @@ -1967,6 +1984,8 @@ public void writeToParcel(Parcel dest, int parcelableFlags) { dest.writeInt(flags); dest.writeInt(privateFlags); dest.writeInt(privateFlagsExt); + dest.writeInt(overrideRes); + dest.writeInt(overrideDensity); dest.writeInt(requiresSmallestWidthDp); dest.writeInt(compatibleWidthLimitDp); dest.writeInt(largestWidthLimitDp); @@ -2070,6 +2089,8 @@ private ApplicationInfo(Parcel source) { flags = source.readInt(); privateFlags = source.readInt(); privateFlagsExt = source.readInt(); + overrideRes = source.readInt(); + overrideDensity = source.readInt(); requiresSmallestWidthDp = source.readInt(); compatibleWidthLimitDp = source.readInt(); largestWidthLimitDp = source.readInt(); @@ -2622,6 +2643,11 @@ public String[] getAllApkPaths() { return output.toArray(new String[output.size()]); } + /** @hide */ + public int getOverrideDensity() { + return overrideDensity; + } + /** {@hide} */ public void setCodePath(String codePath) { scanSourceDir = codePath; } /** {@hide} */ public void setBaseCodePath(String baseCodePath) { sourceDir = baseCodePath; } /** {@hide} */ public void setSplitCodePaths(String[] splitCodePaths) { splitSourceDirs = splitCodePaths; } @@ -2637,6 +2663,7 @@ public String[] getAllApkPaths() { public void setRequestRawExternalStorageAccess(@Nullable Boolean value) { requestRawExternalStorageAccess = value; } + /** {@hide} */ public void setOverrideRes(int overrideResolution) { overrideRes = overrideResolution; } /** * Replaces {@link #mAppClassNamesByProcess}. This takes over the ownership of the passed map. @@ -2672,7 +2699,6 @@ public void setAppClassNamesByProcess(@Nullable ArrayMap value) public int getMemtagMode() { return memtagMode; } - /** * Returns whether the application has requested automatic zero-initialization of native heap * memory allocations to be enabled or disabled. @@ -2769,4 +2795,6 @@ public void setEnableOnBackInvokedCallback(boolean isEnable) { privateFlagsExt &= ~PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK; } } + + /** {@hide} */ public int canOverrideRes() { return overrideRes; } } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index c01e30ded50e..2205b174c020 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -4728,10 +4728,8 @@ private void setActivityResizeMode(ActivityInfo aInfo, TypedArray sa, Package ow * ratio set. */ private void setMaxAspectRatio(Package owner) { - // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater. - // NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD. - float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O - ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0; + // Start at an unlimited aspect ratio unless we get a more restrictive one + float maxAspectRatio = 0; if (owner.applicationInfo.maxAspectRatio != 0) { // Use the application max aspect ration as default if set. diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index e146bb9e20e2..9d24a00b1478 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -34,6 +34,7 @@ import android.view.MotionEvent; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; +import android.util.Log; /** * CompatibilityInfo class keeps the information about the screen compatibility mode that the @@ -47,6 +48,8 @@ public class CompatibilityInfo implements Parcelable { public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() { }; + static final String TAG = "CompatibilityInfo"; + /** * This is the number of pixels we would like to have along the * short axis of an app that needs to run on a normal size screen. @@ -163,11 +166,18 @@ public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw, // Let the user decide. compatFlags |= NEEDS_SCREEN_COMPAT; } - - // Modern apps always support densities. - applicationDensity = DisplayMetrics.DENSITY_DEVICE; - applicationScale = 1.0f; - applicationInvertedScale = 1.0f; + int density = appInfo.getOverrideDensity(); + if(density != 0) { + applicationDensity = density; + applicationScale = DisplayMetrics.DENSITY_DEVICE / (float) applicationDensity; + applicationInvertedScale = 1.0f / applicationScale; + compatFlags |= SCALING_REQUIRED; + } else { + // Modern apps always support densities. + applicationDensity = DisplayMetrics.DENSITY_DEVICE; + applicationScale = 1.0f; + applicationInvertedScale = 1.0f; + } } else { /** @@ -254,26 +264,31 @@ public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw, compatFlags |= NEVER_NEEDS_COMPAT; } - if (overrideScale != 1.0f) { + int density = appInfo.getOverrideDensity(); + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { + applicationDensity = DisplayMetrics.DENSITY_DEFAULT; + applicationScale = DisplayMetrics.DENSITY_DEVICE + / (float) DisplayMetrics.DENSITY_DEFAULT; + applicationInvertedScale = 1.0f / applicationScale; + compatFlags |= SCALING_REQUIRED; + } else if((density != 0) || (overrideScale != 1.0f)) { applicationScale = overrideScale; applicationInvertedScale = 1.0f / overrideScale; applicationDensity = (int) ((DisplayMetrics.DENSITY_DEVICE_STABLE * applicationInvertedScale) + .5f); compatFlags |= HAS_OVERRIDE_SCALING; - } else if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { + } else { applicationDensity = DisplayMetrics.DENSITY_DEVICE; applicationScale = 1.0f; applicationInvertedScale = 1.0f; - } else { - applicationDensity = DisplayMetrics.DENSITY_DEFAULT; - applicationScale = DisplayMetrics.DENSITY_DEVICE - / (float) DisplayMetrics.DENSITY_DEFAULT; - applicationInvertedScale = 1.0f / applicationScale; - compatFlags |= SCALING_REQUIRED; } } mCompatibilityFlags = compatFlags; + + Log.d(TAG, "mCompatibilityFlags - " + Integer.toHexString(mCompatibilityFlags)); + Log.d(TAG, "applicationDensity - " + applicationDensity); + Log.d(TAG, "applicationScale - " + applicationScale); } private CompatibilityInfo(int compFlags, diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java index 3270944ce7e3..e0701b90d6fa 100644 --- a/core/java/android/content/res/ThemedResourceCache.java +++ b/core/java/android/content/res/ThemedResourceCache.java @@ -22,10 +22,10 @@ import android.content.pm.ActivityInfo.Config; import android.content.res.Resources.Theme; import android.content.res.Resources.ThemeKey; -import android.util.ArrayMap; import android.util.LongSparseArray; import java.lang.ref.WeakReference; +import java.util.HashMap; /** * Data structure used for caching data against themes. @@ -34,7 +34,7 @@ */ abstract class ThemedResourceCache { @UnsupportedAppUsage - private ArrayMap>> mThemedEntries; + private HashMap>> mThemedEntries; private LongSparseArray> mUnthemedEntries; private LongSparseArray> mNullThemedEntries; @@ -154,7 +154,7 @@ private LongSparseArray> getThemedLocked(@Nullable Theme t, boo if (mThemedEntries == null) { if (create) { - mThemedEntries = new ArrayMap<>(1); + mThemedEntries = new HashMap<>(1); } else { return null; } @@ -199,11 +199,8 @@ private LongSparseArray> getUnthemedLocked(boolean create) { private boolean prune(@Config int configChanges) { synchronized (this) { if (mThemedEntries != null) { - for (int i = mThemedEntries.size() - 1; i >= 0; i--) { - if (pruneEntriesLocked(mThemedEntries.valueAt(i), configChanges)) { - mThemedEntries.removeAt(i); - } - } + mThemedEntries.entrySet() + .removeIf(entry -> pruneEntriesLocked(entry.getValue(), configChanges)); } pruneEntriesLocked(mNullThemedEntries, configChanges); diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java index 830584314039..bc6368639baa 100644 --- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java +++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java @@ -299,7 +299,7 @@ boolean isLookasideConfigSet() { if (isLegacyCompatibilityWalEnabled()) { return SQLiteCompatibilityWalFlags.getWALSyncMode(); } else { - return SQLiteGlobal.getDefaultSyncMode(); + return SQLiteGlobal.getWALSyncMode(); } } else { return SQLiteGlobal.getDefaultSyncMode(); diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index e986320b4a9f..0c71c7728c80 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -171,6 +171,10 @@ public class Camera { private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200; private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400; private static final int CAMERA_MSG_FOCUS_MOVE = 0x800; + /* ### QC ADD-ONS: START */ + private static final int CAMERA_MSG_STATS_DATA = 0x1000; + private static final int CAMERA_MSG_META_DATA = 0x2000; + /* ### QC ADD-ONS: END */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private long mNativeContext; // accessed by native methods @@ -202,7 +206,17 @@ public class Camera { private boolean mShutterSoundEnabledFromApp = true; private static final int NO_ERROR = 0; - + private static final int EACCESS = -13; + private static final int ENODEV = -19; + private static final int EBUSY = -16; + private static final int EINVAL = -22; + private static final int ENOSYS = -38; + private static final int EUSERS = -87; + private static final int EOPNOTSUPP = -95; + /* ### QC ADD-ONS: START */ + private CameraDataCallback mCameraDataCallback; + private CameraMetaDataCallback mCameraMetaDataCallback; + /* ### QC ADD-ONS: END */ /** * Broadcast Action: A new picture is taken by the camera, and the entry of * the picture has been added to the media store. @@ -273,6 +287,8 @@ public static boolean shouldExposeAuxCamera() { * if the package name does not falls in this bucket */ String packageName = ActivityThread.currentOpPackageName(); + if (packageName == null) + return true; List packageList = new ArrayList<>(Arrays.asList( SystemProperties.get("vendor.camera.aux.packagelist", ",").split(","))); List packageExcludelist = new ArrayList<>(Arrays.asList( @@ -368,10 +384,22 @@ public static class CameraInfo { */ public static final int CAMERA_FACING_FRONT = 1; + /* ### QC ADD-ONS: START TBD*/ + /** @hide + * camera is in ZSL mode. + */ + public static final int CAMERA_SUPPORT_MODE_ZSL = 2; + + /** @hide + * camera is in non-ZSL mode. + */ + public static final int CAMERA_SUPPORT_MODE_NONZSL = 3; + /* ### QC ADD-ONS: END */ /** * The direction that the camera faces. It should be * CAMERA_FACING_BACK or CAMERA_FACING_FRONT. */ + public int facing; /** @@ -519,6 +547,10 @@ private int cameraInit(int cameraId) { mPostviewCallback = null; mUsingPreviewAllocation = false; mZoomListener = null; + /* ### QC ADD-ONS: START */ + mCameraDataCallback = null; + mCameraMetaDataCallback = null; + /* ### QC ADD-ONS: END */ Looper looper; if ((looper = Looper.myLooper()) != null) { @@ -1278,7 +1310,22 @@ public void handleMessage(Message msg) { mAutoFocusMoveCallback.onAutoFocusMoving(msg.arg1 == 0 ? false : true, mCamera); } return; - + /* ### QC ADD-ONS: START */ + case CAMERA_MSG_STATS_DATA: + int statsdata[] = new int[257]; + for(int i =0; i<257; i++ ) { + statsdata[i] = byteToInt( (byte[])msg.obj, i*4); + } + if (mCameraDataCallback != null) { + mCameraDataCallback.onCameraData(statsdata, mCamera); + } + return; + case CAMERA_MSG_META_DATA: + if (mCameraMetaDataCallback != null) { + mCameraMetaDataCallback.onCameraMetaData((byte[])msg.obj, mCamera); + } + return; + /* ### QC ADD-ONS: END */ default: Log.e(TAG, "Unknown message type " + msg.what); return; @@ -1789,7 +1836,11 @@ private void updateAppOpsPlayAudio() { } catch (RemoteException e) { Log.e(TAG, "Audio service is unavailable for queries"); } - _enableShutterSound(false); + try { + _enableShutterSound(false); + } catch (Exception e) { + Log.e(TAG, "Couldn't disable shutter sound"); + } } else { enableShutterSound(mShutterSoundEnabledFromApp); } @@ -2155,7 +2206,157 @@ public static Parameters getEmptyParameters() { Camera camera = new Camera(); return camera.new Parameters(); } + /* ### QC ADD-ONS: START */ + private static int byteToInt(byte[] b, int offset) { + int value = 0; + for (int i = 0; i < 4; i++) { + int shift = (4 - 1 - i) * 8; + value += (b[(3-i) + offset] & 0x000000FF) << shift; + } + return value; + } + /** @hide + * Handles the callback for when Camera Data is available. + * data is read from the camera. + */ + public interface CameraDataCallback { + /** + * Callback for when camera data is available. + * + * @param data a int array of the camera data + * @param camera the Camera service object + */ + void onCameraData(int[] data, Camera camera); + }; + + /** @hide + * Set camera histogram mode and registers a callback function to run. + * Only valid after startPreview() has been called. + * + * @param cb the callback to run + */ + public final void setHistogramMode(CameraDataCallback cb) + { + mCameraDataCallback = cb; + native_setHistogramMode(cb!=null); + } + private native final void native_setHistogramMode(boolean mode); + + /** @hide + * Set camera histogram command to send data. + * + */ + public final void sendHistogramData() + { + native_sendHistogramData(); + } + private native final void native_sendHistogramData(); + + /** @hide + * Handles the callback for when Camera Meta Data is available. + * Meta data is read from the camera. + */ + public interface CameraMetaDataCallback { + /** + * Callback for when camera meta data is available. + * + * @param data a byte array of the camera meta data + * @param camera the Camera service object + */ + void onCameraMetaData(byte[] data, Camera camera); + }; + + /** @hide + * Set camera meta data and registers a callback function to run. + * Only valid after startPreview() has been called. + * + * @param cb the callback to run + */ + public final void setMetadataCb(CameraMetaDataCallback cb) + { + mCameraMetaDataCallback = cb; + native_setMetadataCb(cb!=null); + } + private native final void native_setMetadataCb(boolean mode); + + /** @hide + * Set camera face detection command to send meta data. + */ + public final void sendMetaData() + { + native_sendMetaData(); + } + private native final void native_sendMetaData(); + + /** @hide + * Configure longshot mode. Available only in ZSL. + * + * @param enable enable/disable this mode + */ + public final void setLongshot(boolean enable) + { + native_setLongshot(enable); + } + private native final void native_setLongshot(boolean enable); + + /** @hide + * Handles the Touch Co-ordinate. + */ + public class Coordinate { + /** + * Sets the x,y co-ordinates for a touch event + * + * @param x the x co-ordinate (pixels) + * @param y the y co-ordinate (pixels) + */ + public Coordinate(int x, int y) { + xCoordinate = x; + yCoordinate = y; + } + /** + * Compares {@code obj} to this co-ordinate. + * + * @param obj the object to compare this co-ordinate with. + * @return {@code true} if the xCoordinate and yCoordinate of {@code obj} is the + * same as those of this coordinate. {@code false} otherwise. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Coordinate)) { + return false; + } + Coordinate c = (Coordinate) obj; + return xCoordinate == c.xCoordinate && yCoordinate == c.yCoordinate; + } + + /** x co-ordinate for the touch event*/ + public int xCoordinate; + + /** y co-ordinate for the touch event */ + public int yCoordinate; + }; + + /** @hide + * Returns the current focus position. + * + * If it's in AF mode, it's the lens position after af is done. + * + * If it's in Manual Focus mode, it actually returns the value + * set by user via {@link #setParameters(Camera.Parameters)}. + */ + public int getCurrentFocusPosition() { + Parameters p = new Parameters(); + String s = native_getParameters(); + p.unflatten(s); + + int focus_pos = -1; + if (p.getCurrentFocusPosition() != null) { + focus_pos = Integer.parseInt(p.getCurrentFocusPosition()); + } + return focus_pos; + } + /* ### QC ADD-ONS: END */ /** * Returns a copied {@link Parameters}; for shim use only. * @@ -2417,6 +2618,10 @@ public class Parameters { public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight"; public static final String WHITE_BALANCE_TWILIGHT = "twilight"; public static final String WHITE_BALANCE_SHADE = "shade"; + /** @hide + * wb manual cct mode. + */ + public static final String WHITE_BALANCE_MANUAL_CCT = "manual-cct"; // Values for color effect settings. public static final String EFFECT_NONE = "none"; @@ -2463,6 +2668,10 @@ public class Parameters { * This can also be used for video recording. */ public static final String FLASH_MODE_TORCH = "torch"; + /** @hide + * Scene mode is off. + */ + public static final String SCENE_MODE_ASD = "asd"; /** * Scene mode is off. @@ -2540,6 +2749,14 @@ public class Parameters { * Capture the naturally warm color of scenes lit by candles. */ public static final String SCENE_MODE_CANDLELIGHT = "candlelight"; + /** @hide + * SCENE_MODE_BACKLIGHT + **/ + public static final String SCENE_MODE_BACKLIGHT = "backlight"; + /** @hide + * SCENE_MODE_FLOWERS + **/ + public static final String SCENE_MODE_FLOWERS = "flowers"; /** * Applications are looking for a barcode. Camera driver will be @@ -2581,6 +2798,12 @@ public class Parameters { * not call {@link #autoFocus(AutoFocusCallback)} in this mode. */ public static final String FOCUS_MODE_FIXED = "fixed"; + /** @hide + * Normal focus mode. Applications should call + * {@link #autoFocus(AutoFocusCallback)} to start the focus in this + * mode. + */ + public static final String FOCUS_MODE_NORMAL = "normal"; /** * Extended depth of field (EDOF). Focusing is done digitally and @@ -2633,7 +2856,10 @@ public class Parameters { * @see #FOCUS_MODE_CONTINUOUS_VIDEO */ public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture"; - + /** @hide + * manual focus mode + */ + public static final String FOCUS_MODE_MANUAL_POSITION = "manual"; // Indices for focus distance array. /** * The array index of near focus distance for use with @@ -2670,6 +2896,7 @@ public class Parameters { // Formats for setPreviewFormat and setPictureFormat. private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp"; private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp"; + private static final String PIXEL_FORMAT_YUV420SP_ADRENO = "yuv420sp-adreno"; private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv"; private static final String PIXEL_FORMAT_YUV420P = "yuv420p"; private static final String PIXEL_FORMAT_RGB565 = "rgb565"; @@ -4519,5 +4746,1231 @@ private boolean same(String s1, String s2) { if (s1 != null && s1.equals(s2)) return true; return false; } + /* ### QC ADD-ONS: START */ + + /* ### QC ADDED PARAMETER KEYS*/ + private static final String KEY_QC_HFR_SIZE = "hfr-size"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_MODE = "preview-frame-rate-mode"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_AUTO_MODE = "frame-rate-auto"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_FIXED_MODE = "frame-rate-fixed"; + private static final String KEY_QC_GPS_LATITUDE_REF = "gps-latitude-ref"; + private static final String KEY_QC_GPS_LONGITUDE_REF = "gps-longitude-ref"; + private static final String KEY_QC_GPS_ALTITUDE_REF = "gps-altitude-ref"; + private static final String KEY_QC_GPS_STATUS = "gps-status"; + private static final String KEY_QC_EXIF_DATETIME = "exif-datetime"; + private static final String KEY_QC_TOUCH_AF_AEC = "touch-af-aec"; + private static final String KEY_QC_TOUCH_INDEX_AEC = "touch-index-aec"; + private static final String KEY_QC_TOUCH_INDEX_AF = "touch-index-af"; + private static final String KEY_QC_MANUAL_FOCUS_POSITION = "manual-focus-position"; + private static final String KEY_QC_MANUAL_FOCUS_POS_TYPE = "manual-focus-pos-type"; + private static final String KEY_QC_SCENE_DETECT = "scene-detect"; + private static final String KEY_QC_ISO_MODE = "iso"; + private static final String KEY_QC_EXPOSURE_TIME = "exposure-time"; + private static final String KEY_QC_MIN_EXPOSURE_TIME = "min-exposure-time"; + private static final String KEY_QC_MAX_EXPOSURE_TIME = "max-exposure-time"; + private static final String KEY_QC_LENSSHADE = "lensshade"; + private static final String KEY_QC_HISTOGRAM = "histogram"; + private static final String KEY_QC_SKIN_TONE_ENHANCEMENT = "skinToneEnhancement"; + private static final String KEY_QC_AUTO_EXPOSURE = "auto-exposure"; + private static final String KEY_QC_SHARPNESS = "sharpness"; + private static final String KEY_QC_MAX_SHARPNESS = "max-sharpness"; + private static final String KEY_QC_CONTRAST = "contrast"; + private static final String KEY_QC_MAX_CONTRAST = "max-contrast"; + private static final String KEY_QC_SATURATION = "saturation"; + private static final String KEY_QC_MAX_SATURATION = "max-saturation"; + private static final String KEY_QC_DENOISE = "denoise"; + private static final String KEY_QC_CONTINUOUS_AF = "continuous-af"; + private static final String KEY_QC_SELECTABLE_ZONE_AF = "selectable-zone-af"; + private static final String KEY_QC_FACE_DETECTION = "face-detection"; + private static final String KEY_QC_MEMORY_COLOR_ENHANCEMENT = "mce"; + private static final String KEY_QC_REDEYE_REDUCTION = "redeye-reduction"; + private static final String KEY_QC_ZSL = "zsl"; + private static final String KEY_QC_CAMERA_MODE = "camera-mode"; + private static final String KEY_QC_VIDEO_HIGH_FRAME_RATE = "video-hfr"; + private static final String KEY_QC_VIDEO_HDR = "video-hdr"; + private static final String KEY_QC_POWER_MODE = "power-mode"; + private static final String KEY_QC_POWER_MODE_SUPPORTED = "power-mode-supported"; + private static final String KEY_QC_WB_MANUAL_CCT = "wb-manual-cct"; + private static final String KEY_QC_MIN_WB_CCT = "min-wb-cct"; + private static final String KEY_QC_MAX_WB_CCT = "max-wb-cct"; + private static final String KEY_QC_AUTO_HDR_ENABLE = "auto-hdr-enable"; + private static final String KEY_QC_VIDEO_ROTATION = "video-rotation"; + + /** @hide + * KEY_QC_AE_BRACKET_HDR + **/ + public static final String KEY_QC_AE_BRACKET_HDR = "ae-bracket-hdr"; + + /* ### QC ADDED PARAMETER VALUES*/ + + // Values for touch af/aec settings. + /** @hide + * TOUCH_AF_AEC_OFF + **/ + public static final String TOUCH_AF_AEC_OFF = "touch-off"; + /** @hide + * TOUCH_AF_AEC_ON + **/ + public static final String TOUCH_AF_AEC_ON = "touch-on"; + + // Values for auto exposure settings. + /** @hide + * Auto exposure frame-avg + **/ + public static final String AUTO_EXPOSURE_FRAME_AVG = "frame-average"; + /** @hide + * Auto exposure center weighted + **/ + public static final String AUTO_EXPOSURE_CENTER_WEIGHTED = "center-weighted"; + /** @hide + * Auto exposure spot metering + **/ + public static final String AUTO_EXPOSURE_SPOT_METERING = "spot-metering"; + + //Values for ISO settings + /** @hide + * ISO_AUTO + **/ + public static final String ISO_AUTO = "auto"; + /** @hide + * ISO_HJR + **/ + public static final String ISO_HJR = "ISO_HJR"; + /** @hide + * ISO_100 + **/ + public static final String ISO_100 = "ISO100"; + /** @hide + * ISO_200 + **/ + public static final String ISO_200 = "ISO200"; + /** @hide + * ISO_400 + **/ + public static final String ISO_400 = "ISO400"; + /** @hide + * ISO_800 + **/ + public static final String ISO_800 = "ISO800"; + /** @hide + * ISO_1600 + **/ + public static final String ISO_1600 = "ISO1600"; + + /** @hide + * ISO_3200 + **/ + public static final String ISO_3200 = "ISO3200"; + + //Values for Lens Shading + /** @hide + * LENSSHADE_ENABLE + **/ + public static final String LENSSHADE_ENABLE = "enable"; + /** @hide + * LENSSHADE_DISABLE + **/ + public static final String LENSSHADE_DISABLE= "disable"; + + //Values for Histogram + /** @hide + * Histogram enable + **/ + public static final String HISTOGRAM_ENABLE = "enable"; + /** @hide + * Histogram disable + **/ + public static final String HISTOGRAM_DISABLE= "disable"; + + //Values for Skin Tone Enhancement + /** @hide + * SKIN_TONE_ENHANCEMENT_ENABLE + **/ + public static final String SKIN_TONE_ENHANCEMENT_ENABLE = "enable"; + /** @hide + * SKIN_TONE_ENHANCEMENT_DISABLE + **/ + public static final String SKIN_TONE_ENHANCEMENT_DISABLE= "disable"; + + // Values for MCE settings. + /** @hide + * MCE_ENaBLE + **/ + public static final String MCE_ENABLE = "enable"; + /** @hide + * MCE_DISABLE + **/ + public static final String MCE_DISABLE = "disable"; + + // Values for ZSL settings. + /** @hide + * ZSL_ON + **/ + public static final String ZSL_ON = "on"; + /** @hide + * ZSL_OFF + **/ + public static final String ZSL_OFF = "off"; + + // Values for HDR Bracketing settings. + + /** @hide + * AEC bracketing off + **/ + public static final String AE_BRACKET_HDR_OFF = "Off"; + /** @hide + * AEC bracketing hdr + **/ + public static final String AE_BRACKET_HDR = "HDR"; + /** @hide + * AEC bracketing aec-bracket + **/ + public static final String AE_BRACKET = "AE-Bracket"; + + // Values for Power mode. + /** @hide + * LOW_POWER + **/ + public static final String LOW_POWER = "Low_Power"; + /** @hide + * NORMAL_POWER + **/ + public static final String NORMAL_POWER = "Normal_Power"; + + // Values for HFR settings. + /** @hide + * VIDEO_HFR_OFF + **/ + public static final String VIDEO_HFR_OFF = "off"; + /** @hide + * VIDEO_HFR_2X + **/ + public static final String VIDEO_HFR_2X = "60"; + /** @hide + * VIDEO_HFR_3X + **/ + public static final String VIDEO_HFR_3X = "90"; + /** @hide + * VIDEO_HFR_4X + **/ + public static final String VIDEO_HFR_4X = "120"; + + // Values for auto scene detection settings. + /** @hide + * SCENE_DETECT_OFF + **/ + public static final String SCENE_DETECT_OFF = "off"; + /** @hide + * SCENE_DETECT_ON + **/ + public static final String SCENE_DETECT_ON = "on"; + + //Values for Continuous AF + + /** @hide + * CAF off + **/ + public static final String CONTINUOUS_AF_OFF = "caf-off"; + /** @hide + * CAF on + **/ + public static final String CONTINUOUS_AF_ON = "caf-on"; + /** @hide + * Denoise off + **/ + public static final String DENOISE_OFF = "denoise-off"; + /** @hide + * Denoise on + **/ + public static final String DENOISE_ON = "denoise-on"; + + // Values for Redeye Reduction settings. + /** @hide + * REDEYE_REDUCTION_ENABLE + **/ + public static final String REDEYE_REDUCTION_ENABLE = "enable"; + /** @hide + * REDEYE_REDUCTION_DISABLE + **/ + public static final String REDEYE_REDUCTION_DISABLE = "disable"; + + // Values for selectable zone af settings. + /** @hide + * SELECTABLE_ZONE_AF_AUTO + **/ + public static final String SELECTABLE_ZONE_AF_AUTO = "auto"; + /** @hide + * SELECTABLE_ZONE_AF_SPOTMETERING + **/ + public static final String SELECTABLE_ZONE_AF_SPOTMETERING = "spot-metering"; + /** @hide + * SELECTABLE_ZONE_AF_CENTER_WEIGHTED + **/ + public static final String SELECTABLE_ZONE_AF_CENTER_WEIGHTED = "center-weighted"; + /** @hide + * SELECTABLE_ZONE_AF_FRAME_AVERAGE + **/ + public static final String SELECTABLE_ZONE_AF_FRAME_AVERAGE = "frame-average"; + + // Values for Face Detection settings. + /** @hide + * Face Detection off + **/ + public static final String FACE_DETECTION_OFF = "off"; + /** @hide + * Face Detction on + **/ + public static final String FACE_DETECTION_ON = "on"; + + // Values for video rotation settings. + + /** @hide + * VIDEO_ROTATION_0 + **/ + public static final String VIDEO_ROTATION_0 = "0"; + /** @hide + * VIDEO_ROTATION_90 + **/ + public static final String VIDEO_ROTATION_90 = "90"; + /** @hide + * VIDEO_ROTATION_180 + **/ + public static final String VIDEO_ROTATION_180 = "180"; + /** @hide + * VIDEO_ROTATION_270 + **/ + public static final String VIDEO_ROTATION_270 = "270"; + + /* ### QC ADDED PARAMETER APIS*/ + /** @hide + * Gets the supported preview sizes in high frame rate recording mode. + * + * @return a list of Size object. This method will always return a list + * with at least one element. + */ + public List getSupportedHfrSizes() { + String str = get(KEY_QC_HFR_SIZE + SUPPORTED_VALUES_SUFFIX); + return splitSize(str); + } + + /** @hide + * Gets the supported Touch AF/AEC setting. + * + * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC + * setting is not supported. + * + */ + public List getSupportedTouchAfAec() { + String str = get(KEY_QC_TOUCH_AF_AEC + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** + * Gets the supported Touch AF/AEC setting. + * + * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC + * setting is not supported. + * + */ + + /** @hide + * Gets the supported frame rate modes. + * + * @return a List of FRAME_RATE_XXX_MODE string constant. null if this + * setting is not supported. + */ + public List getSupportedPreviewFrameRateModes() { + String str = get(KEY_QC_PREVIEW_FRAME_RATE_MODE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported auto scene detection modes. + * + * @return a List of SCENE_DETECT_XXX string constant. null if scene detection + * setting is not supported. + * + */ + public List getSupportedSceneDetectModes() { + String str = get(KEY_QC_SCENE_DETECT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported ISO values. + * + * @return a List of FLASH_MODE_XXX string constants. null if flash mode + * setting is not supported. + */ + public List getSupportedIsoValues() { + String str = get(KEY_QC_ISO_MODE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Lensshade modes. + * + * @return a List of LENS_MODE_XXX string constants. null if lens mode + * setting is not supported. + */ + public List getSupportedLensShadeModes() { + String str = get(KEY_QC_LENSSHADE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Histogram modes. + * + * @return a List of HISTOGRAM_XXX string constants. null if histogram mode + * setting is not supported. + */ + public List getSupportedHistogramModes() { + String str = get(KEY_QC_HISTOGRAM + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Skin Tone Enhancement modes. + * + * @return a List of SKIN_TONE_ENHANCEMENT_XXX string constants. null if skin tone enhancement + * setting is not supported. + */ + public List getSupportedSkinToneEnhancementModes() { + String str = get(KEY_QC_SKIN_TONE_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported auto exposure setting. + * + * @return a List of AUTO_EXPOSURE_XXX string constants. null if auto exposure + * setting is not supported. + */ + public List getSupportedAutoexposure() { + String str = get(KEY_QC_AUTO_EXPOSURE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported MCE modes. + * + * @return a List of MCE_ENABLE/DISABLE string constants. null if MCE mode + * setting is not supported. + */ + public List getSupportedMemColorEnhanceModes() { + String str = get(KEY_QC_MEMORY_COLOR_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported ZSL modes. + * + * @return a List of ZSL_OFF/OFF string constants. null if ZSL mode + * setting is not supported. + */ + public List getSupportedZSLModes() { + String str = get(KEY_QC_ZSL + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Video HDR modes. + * + * @return a List of Video HDR_OFF/OFF string constants. null if + * Video HDR mode setting is not supported. + */ + public List getSupportedVideoHDRModes() { + String str = get(KEY_QC_VIDEO_HDR + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported HFR modes. + * + * @return a List of VIDEO_HFR_XXX string constants. null if hfr mode + * setting is not supported. + */ + public List getSupportedVideoHighFrameRateModes() { + String str = get(KEY_QC_VIDEO_HIGH_FRAME_RATE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Continuous AF modes. + * + * @return a List of CONTINUOUS_AF_XXX string constant. null if continuous AF + * setting is not supported. + * + */ + public List getSupportedContinuousAfModes() { + String str = get(KEY_QC_CONTINUOUS_AF + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported DENOISE modes. + * + * @return a List of DENOISE_XXX string constant. null if DENOISE + * setting is not supported. + * + */ + public List getSupportedDenoiseModes() { + String str = get(KEY_QC_DENOISE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported selectable zone af setting. + * + * @return a List of SELECTABLE_ZONE_AF_XXX string constants. null if selectable zone af + * setting is not supported. + */ + public List getSupportedSelectableZoneAf() { + String str = get(KEY_QC_SELECTABLE_ZONE_AF + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported face detection modes. + * + * @return a List of FACE_DETECTION_XXX string constant. null if face detection + * setting is not supported. + * + */ + public List getSupportedFaceDetectionModes() { + String str = get(KEY_QC_FACE_DETECTION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported redeye reduction modes. + * + * @return a List of REDEYE_REDUCTION_XXX string constant. null if redeye reduction + * setting is not supported. + * + */ + public List getSupportedRedeyeReductionModes() { + String str = get(KEY_QC_REDEYE_REDUCTION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Sets GPS altitude reference. This will be stored in JPEG EXIF header. + * @param altRef reference GPS altitude in meters. + */ + public void setGpsAltitudeRef(double altRef) { + set(KEY_QC_GPS_ALTITUDE_REF, Double.toString(altRef)); + } + + /** @hide + * Sets GPS Status. This will be stored in JPEG EXIF header. + * + * @param status GPS status (UTC in seconds since January 1, + * 1970). + */ + public void setGpsStatus(double status) { + set(KEY_QC_GPS_STATUS, Double.toString(status)); + } + + /** @hide + * Sets the touch co-ordinate for Touch AEC. + * + * @param x the x co-ordinate of the touch event + * @param y the y co-ordinate of the touch event + * + */ + public void setTouchIndexAec(int x, int y) { + String v = Integer.toString(x) + "x" + Integer.toString(y); + set(KEY_QC_TOUCH_INDEX_AEC, v); + } + + /** @hide + * Returns the touch co-ordinates of the touch event. + * + * @return a Index object with the x and y co-ordinated + * for the touch event + * + */ + public Coordinate getTouchIndexAec() { + String pair = get(KEY_QC_TOUCH_INDEX_AEC); + return strToCoordinate(pair); + } + + /** @hide + * Sets the touch co-ordinate for Touch AF. + * + * @param x the x co-ordinate of the touch event + * @param y the y co-ordinate of the touch event + * + */ + public void setTouchIndexAf(int x, int y) { + String v = Integer.toString(x) + "x" + Integer.toString(y); + set(KEY_QC_TOUCH_INDEX_AF, v); + } + + /** @hide + * Returns the touch co-ordinates of the touch event. + * + * @return a Index object with the x and y co-ordinated + * for the touch event + * + */ + public Coordinate getTouchIndexAf() { + String pair = get(KEY_QC_TOUCH_INDEX_AF); + return strToCoordinate(pair); + } + /** @hide + * Set Sharpness Level + * + * @param sharpness level + */ + public void setSharpness(int sharpness){ + if((sharpness < 0) || (sharpness > getMaxSharpness()) ) + throw new IllegalArgumentException( + "Invalid Sharpness " + sharpness); + + set(KEY_QC_SHARPNESS, String.valueOf(sharpness)); + } + + /** @hide + * Set Contrast Level + * + * @param contrast level + */ + public void setContrast(int contrast){ + if((contrast < 0 ) || (contrast > getMaxContrast())) + throw new IllegalArgumentException( + "Invalid Contrast " + contrast); + + set(KEY_QC_CONTRAST, String.valueOf(contrast)); + } + + /** @hide + * Set Saturation Level + * + * @param saturation level + */ + public void setSaturation(int saturation){ + if((saturation < 0 ) || (saturation > getMaxSaturation())) + throw new IllegalArgumentException( + "Invalid Saturation " + saturation); + + set(KEY_QC_SATURATION, String.valueOf(saturation)); + } + + /** @hide + * @return true if full size video snapshot is supported. + */ + public boolean isPowerModeSupported() { + String str = get(KEY_QC_POWER_MODE_SUPPORTED); + return TRUE.equals(str); + } + + /** @hide + * Get Sharpness level + * + * @return sharpness level + */ + public int getSharpness(){ + return getInt(KEY_QC_SHARPNESS); + } + + /** @hide + * Get Max Sharpness Level + * + * @return max sharpness level + */ + public int getMaxSharpness(){ + return getInt(KEY_QC_MAX_SHARPNESS); + } + + /** @hide + * Get Contrast level + * + * @return contrast level + */ + public int getContrast(){ + return getInt(KEY_QC_CONTRAST); + } + + /** @hide + * Get Max Contrast Level + * + * @return max contrast level + */ + public int getMaxContrast(){ + return getInt(KEY_QC_MAX_CONTRAST); + } + + /** @hide + * Get Saturation level + * + * @return saturation level + */ + public int getSaturation(){ + return getInt(KEY_QC_SATURATION); + } + + /** @hide + * Get Max Saturation Level + * + * @return max contrast level + */ + public int getMaxSaturation(){ + return getInt(KEY_QC_MAX_SATURATION); + } + + /** @hide + * Sets GPS latitude reference coordinate. This will be stored in JPEG EXIF + * header. + * @param latRef GPS latitude reference coordinate. + */ + public void setGpsLatitudeRef(String latRef) { + set(KEY_QC_GPS_LATITUDE_REF, latRef); + } + + /** @hide + * Sets GPS longitude reference coordinate. This will be stored in JPEG EXIF + * header. + * @param lonRef GPS longitude reference coordinate. + */ + public void setGpsLongitudeRef(String lonRef) { + set(KEY_QC_GPS_LONGITUDE_REF, lonRef); + } + + /** @hide + * Sets system timestamp. This will be stored in JPEG EXIF header. + * + * @param dateTime current timestamp (UTC in seconds since January 1, + * 1970). + */ + public void setExifDateTime(String dateTime) { + set(KEY_QC_EXIF_DATETIME, dateTime); + } + + /** @hide + * Gets the current Touch AF/AEC setting. + * + * @return one of TOUCH_AF_AEC_XXX string constant. null if Touch AF/AEC + * setting is not supported. + * + */ + public String getTouchAfAec() { + return get(KEY_QC_TOUCH_AF_AEC); + } + + /** @hide + * Sets the current TOUCH AF/AEC setting. + * + * @param value TOUCH_AF_AEC_XXX string constants. + * + */ + public void setTouchAfAec(String value) { + set(KEY_QC_TOUCH_AF_AEC, value); + } + + /** @hide + * Gets the current redeye reduction setting. + * + * @return one of REDEYE_REDUCTION_XXX string constant. null if redeye reduction + * setting is not supported. + * + */ + public String getRedeyeReductionMode() { + return get(KEY_QC_REDEYE_REDUCTION); + } + + /** @hide + * Sets the redeye reduction. Other parameters may be changed after changing + * redeye reduction. After setting redeye reduction, + * applications should call getParameters to know if some parameters are + * changed. + * + * @param value REDEYE_REDUCTION_XXX string constants. + * + */ + public void setRedeyeReductionMode(String value) { + set(KEY_QC_REDEYE_REDUCTION, value); + } + + /** @hide + * Gets the frame rate mode setting. + * + * @return one of FRAME_RATE_XXX_MODE string constant. null if this + * setting is not supported. + */ + public String getPreviewFrameRateMode() { + return get(KEY_QC_PREVIEW_FRAME_RATE_MODE); + } + + /** @hide + * Sets the frame rate mode. + * + * @param value FRAME_RATE_XXX_MODE string constants. + */ + public void setPreviewFrameRateMode(String value) { + set(KEY_QC_PREVIEW_FRAME_RATE_MODE, value); + } + + /** @hide + * Gets the current auto scene detection setting. + * + * @return one of SCENE_DETECT_XXX string constant. null if auto scene detection + * setting is not supported. + * + */ + public String getSceneDetectMode() { + return get(KEY_QC_SCENE_DETECT); + } + + /** @hide + * Sets the auto scene detect. Other parameters may be changed after changing + * scene detect. After setting auto scene detection, + * applications should call getParameters to know if some parameters are + * changed. + * + * @param value SCENE_DETECT_XXX string constants. + * + */ + public void setSceneDetectMode(String value) { + set(KEY_QC_SCENE_DETECT, value); + } + + /** @hide + * Gets the current hdr bracketing mode setting. + * + * @return current hdr bracketing mode. + * @see #KEY_AE_BRACKET_OFF + * @see #KEY_AE_BRACKET_HDR + * @see #KEY_AE_BRACKET_BRACKATING + */ + public String getAEBracket() { + return get(KEY_QC_AE_BRACKET_HDR); + } + + /** @hide + * Sets the Power mode. + * + * @param value Power mode. + * @see #getPowerMode() + */ + public void setPowerMode(String value) { + set(KEY_QC_POWER_MODE, value); + } + + /** @hide + * Gets the current power mode setting. + * + * @return current power mode. null if power mode setting is not + * supported. + * @see #POWER_MODE_LOW + * @see #POWER_MODE_NORMAL + */ + public String getPowerMode() { + return get(KEY_QC_POWER_MODE); + } + + /** @hide + * Set HDR-Bracketing Level + * + * @param value HDR-Bracketing + */ + public void setAEBracket(String value){ + set(KEY_QC_AE_BRACKET_HDR, value); + } + + /** @hide + * Gets the current ISO setting. + * + * @return one of ISO_XXX string constant. null if ISO + * setting is not supported. + */ + public String getISOValue() { + return get(KEY_QC_ISO_MODE); + } + + /** @hide + * Sets the ISO. + * + * @param iso ISO_XXX string constant. + */ + public void setISOValue(String iso) { + set(KEY_QC_ISO_MODE, iso); + } + + /** @hide + * Sets the exposure time. + * + * @param value exposure time. + */ + public void setExposureTime(int value) { + set(KEY_QC_EXPOSURE_TIME, Integer.toString(value)); + } + + /** @hide + * Gets the current exposure time. + * + * @return exposure time. + */ + public String getExposureTime() { + return get(KEY_QC_EXPOSURE_TIME); + } + + /** @hide + * Gets the min supported exposure time. + * + * @return min supported exposure time. + */ + public String getMinExposureTime() { + return get(KEY_QC_MIN_EXPOSURE_TIME); + } + + /** @hide + * Gets the max supported exposure time. + * + * @return max supported exposure time. + */ + public String getMaxExposureTime() { + return get(KEY_QC_MAX_EXPOSURE_TIME); + } + + /** @hide + * Gets the current LensShade Mode. + * + * @return LensShade Mode + */ + public String getLensShade() { + return get(KEY_QC_LENSSHADE); + } + + /** @hide + * Sets the current LensShade Mode. + * + * @return LensShade Mode + */ + public void setLensShade(String lensshade) { + set(KEY_QC_LENSSHADE, lensshade); + } + + /** @hide + * Gets the current auto exposure setting. + * + * @return one of AUTO_EXPOSURE_XXX string constant. null if auto exposure + * setting is not supported. + */ + public String getAutoExposure() { + return get(KEY_QC_AUTO_EXPOSURE); + } + + /** @hide + * Sets the current auto exposure setting. + * + * @param value AUTO_EXPOSURE_XXX string constants. + */ + public void setAutoExposure(String value) { + set(KEY_QC_AUTO_EXPOSURE, value); + } + + /** @hide + * Gets the current MCE Mode. + * + * @return MCE value + */ + public String getMemColorEnhance() { + return get(KEY_QC_MEMORY_COLOR_ENHANCEMENT); + } + + /** @hide + * Sets the current MCE Mode. + * + * @return MCE Mode + */ + public void setMemColorEnhance(String mce) { + set(KEY_QC_MEMORY_COLOR_ENHANCEMENT, mce); + } + + /** @hide + * Set white balance manual cct value. + * + * @param cct user CCT setting. + */ + public void setWBManualCCT(int cct) { + set(KEY_QC_WB_MANUAL_CCT, Integer.toString(cct)); + } + + /** @hide + * Gets the WB min supported CCT. + * + * @return min cct value. + */ + public String getWBMinCCT() { + return get(KEY_QC_MIN_WB_CCT); + } + + /** @hide + * Gets the WB max supported CCT. + * + * @return max cct value. + */ + public String getMaxWBCCT() { + return get(KEY_QC_MAX_WB_CCT); + } + + /** @hide + * Gets the current WB CCT. + * + * @return CCT value + */ + public String getWBCurrentCCT() { + return get(KEY_QC_WB_MANUAL_CCT); + } + + /** @hide + * Gets the current ZSL Mode. + * + * @return ZSL mode value + */ + public String getZSLMode() { + return get(KEY_QC_ZSL); + } + + /** @hide + * Sets the current ZSL Mode. ZSL mode is set as a 0th bit in KEY_CAMERA_MODE. + * + * @return null + */ + public void setZSLMode(String zsl) { + set(KEY_QC_ZSL, zsl); + } + + /** @hide + * Sets the current Auto HDR Mode. + * @ auto_hdr auto hdr string for enable/disable + * @return null + */ + public void setAutoHDRMode(String auto_hdr){ + set(KEY_QC_AUTO_HDR_ENABLE,auto_hdr); + } + + /** @hide + * Gets the current Camera Mode Flag. Camera mode includes a + * flag(byte) which indicates different camera modes. + * For now support for ZSL added at bit0 + * + * @return Camera Mode. + */ + public String getCameraMode() { + return get(KEY_QC_CAMERA_MODE); + } + + /** @hide + * Sets the current Camera Mode. + * + * @return null + */ + public void setCameraMode(int cameraMode) { + set(KEY_QC_CAMERA_MODE, cameraMode); + } + + private static final int MANUAL_FOCUS_POS_TYPE_INDEX = 0; + private static final int MANUAL_FOCUS_POS_TYPE_DAC = 1; + /** @hide + * Set focus position. + * + * @param pos user setting of focus position. + */ + public void setFocusPosition(int type, int pos) { + set(KEY_QC_MANUAL_FOCUS_POS_TYPE, Integer.toString(type)); + set(KEY_QC_MANUAL_FOCUS_POSITION, Integer.toString(pos)); + } + + /** @hide + * Gets the current focus position. + * + * @return current focus position + */ + public String getCurrentFocusPosition() { + return get(KEY_QC_MANUAL_FOCUS_POSITION); + } + + + /** @hide + * Gets the current HFR Mode. + * + * @return VIDEO_HFR_XXX string constants + */ + public String getVideoHighFrameRate() { + return get(KEY_QC_VIDEO_HIGH_FRAME_RATE); + } + + /** @hide + * Sets the current HFR Mode. + * + * @param hfr VIDEO_HFR_XXX string constants + */ + public void setVideoHighFrameRate(String hfr) { + set(KEY_QC_VIDEO_HIGH_FRAME_RATE, hfr); + } + + /** @hide + * Gets the current Video HDR Mode. + * + * @return Video HDR mode value + */ + public String getVideoHDRMode() { + return get(KEY_QC_VIDEO_HDR); + } + + /** @hide + * Sets the current Video HDR Mode. + * + * @return null + */ + public void setVideoHDRMode(String videohdr) { + set(KEY_QC_VIDEO_HDR, videohdr); + } + + /** @hide + * Gets the current DENOISE setting. + * + * @return one of DENOISE_XXX string constant. null if Denoise + * setting is not supported. + * + */ + public String getDenoise() { + return get(KEY_QC_DENOISE); + } + + /** @hide + * Gets the current Continuous AF setting. + * + * @return one of CONTINUOUS_AF_XXX string constant. null if continuous AF + * setting is not supported. + * + */ + public String getContinuousAf() { + return get(KEY_QC_CONTINUOUS_AF); + } + + /** @hide + * Sets the current Denoise mode. + * @param value DENOISE_XXX string constants. + * + */ + + public void setDenoise(String value) { + set(KEY_QC_DENOISE, value); + } + + /** @hide + * Sets the current Continuous AF mode. + * @param value CONTINUOUS_AF_XXX string constants. + * + */ + public void setContinuousAf(String value) { + set(KEY_QC_CONTINUOUS_AF, value); + } + + /** @hide + * Gets the current selectable zone af setting. + * + * @return one of SELECTABLE_ZONE_AF_XXX string constant. null if selectable zone af + * setting is not supported. + */ + public String getSelectableZoneAf() { + return get(KEY_QC_SELECTABLE_ZONE_AF); + } + + /** @hide + * Sets the current selectable zone af setting. + * + * @param value SELECTABLE_ZONE_AF_XXX string constants. + */ + public void setSelectableZoneAf(String value) { + set(KEY_QC_SELECTABLE_ZONE_AF, value); + } + + /** @hide + * Gets the current face detection setting. + * + * @return one of FACE_DETECTION_XXX string constant. null if face detection + * setting is not supported. + * + */ + public String getFaceDetectionMode() { + return get(KEY_QC_FACE_DETECTION); + } + + /** @hide + * Sets the auto scene detect. Other settings like Touch AF/AEC might be + * changed after setting face detection. + * + * @param value FACE_DETECTION_XXX string constants. + * + */ + public void setFaceDetectionMode(String value) { + set(KEY_QC_FACE_DETECTION, value); + } + + /** @hide + * Gets the current video rotation setting. + * + * @return one of VIDEO_QC_ROTATION_XXX string constant. null if video rotation + * setting is not supported. + */ + public String getVideoRotation() { + return get(KEY_QC_VIDEO_ROTATION); + } + + /** @hide + * Sets the current video rotation setting. + * + * @param value VIDEO_QC_ROTATION_XXX string constants. + */ + public void setVideoRotation(String value) { + set(KEY_QC_VIDEO_ROTATION, value); + } + /** @hide + * Gets the supported video rotation modes. + * + * @return a List of VIDEO_QC_ROTATION_XXX string constant. null if this + * setting is not supported. + */ + public List getSupportedVideoRotationValues() { + String str = get(KEY_QC_VIDEO_ROTATION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + // Splits a comma delimited string to an ArrayList of Coordinate. + // Return null if the passing string is null or the Coordinate is 0. + private ArrayList splitCoordinate(String str) { + if (str == null) return null; + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(str); + ArrayList coordinateList = new ArrayList(); + for (String s : splitter) { + Coordinate coordinate = strToCoordinate(s); + if (coordinate != null) coordinateList.add(coordinate); + } + if (coordinateList.size() == 0) return null; + return coordinateList; + } + + // Parses a string (ex: "500x500") to Coordinate object. + // Return null if the passing string is null. + private Coordinate strToCoordinate(String str) { + if (str == null) return null; + + int pos = str.indexOf('x'); + if (pos != -1) { + String x = str.substring(0, pos); + String y = str.substring(pos + 1); + return new Coordinate(Integer.parseInt(x), + Integer.parseInt(y)); + } + Log.e(TAG, "Invalid Coordinate parameter string=" + str); + return null; + } + /* ### QC ADD-ONS: END */ }; } diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 3e5fee84b7be..c75eb45ea3cf 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -162,9 +162,6 @@ public CameraManager(Context context) { private HandlerThread mHandlerThread; private Handler mHandler; private FoldStateListener mFoldStateListener; - @GuardedBy("mLock") - private ArrayList> mDeviceStateListeners = new ArrayList<>(); - private boolean mFoldedDeviceState; /** * @hide @@ -173,31 +170,39 @@ public interface DeviceStateListener { void onDeviceStateChanged(boolean folded); } - private final class FoldStateListener implements DeviceStateManager.DeviceStateCallback { + private static final class FoldStateListener implements DeviceStateManager.DeviceStateCallback { private final int[] mFoldedDeviceStates; + private ArrayList> mDeviceStateListeners = + new ArrayList<>(); + private boolean mFoldedDeviceState; + public FoldStateListener(Context context) { mFoldedDeviceStates = context.getResources().getIntArray( com.android.internal.R.array.config_foldedDeviceStates); } - private void handleStateChange(int state) { + private synchronized void handleStateChange(int state) { boolean folded = ArrayUtils.contains(mFoldedDeviceStates, state); - synchronized (mLock) { - mFoldedDeviceState = folded; - ArrayList> invalidListeners = new ArrayList<>(); - for (WeakReference listener : mDeviceStateListeners) { - DeviceStateListener callback = listener.get(); - if (callback != null) { - callback.onDeviceStateChanged(folded); - } else { - invalidListeners.add(listener); - } - } - if (!invalidListeners.isEmpty()) { - mDeviceStateListeners.removeAll(invalidListeners); + + mFoldedDeviceState = folded; + ArrayList> invalidListeners = new ArrayList<>(); + for (WeakReference listener : mDeviceStateListeners) { + DeviceStateListener callback = listener.get(); + if (callback != null) { + callback.onDeviceStateChanged(folded); + } else { + invalidListeners.add(listener); } } + if (!invalidListeners.isEmpty()) { + mDeviceStateListeners.removeAll(invalidListeners); + } + } + + public synchronized void addDeviceStateListener(DeviceStateListener listener) { + listener.onDeviceStateChanged(mFoldedDeviceState); + mDeviceStateListeners.add(new WeakReference<>(listener)); } @Override @@ -221,9 +226,8 @@ public final void onStateChanged(int state) { public void registerDeviceStateListener(@NonNull CameraCharacteristics chars) { synchronized (mLock) { DeviceStateListener listener = chars.getDeviceStateListener(); - listener.onDeviceStateChanged(mFoldedDeviceState); if (mFoldStateListener != null) { - mDeviceStateListeners.add(new WeakReference<>(listener)); + mFoldStateListener.addDeviceStateListener(listener); } } } diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java index 8bf94986a490..741423410efc 100644 --- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java +++ b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java @@ -74,6 +74,19 @@ public CaptureResultExtras(int requestId, int subsequenceId, int afTriggerId, this.hasReadoutTimestamp = hasReadoutTimestamp; this.readoutTimestamp = readoutTimestamp; } + // Backwards-compatible constructor + public CaptureResultExtras(int requestId, int subsequenceId, int afTriggerId, + int precaptureTriggerId, long frameNumber, + int partialResultCount, int errorStreamId, + String errorPhysicalCameraId, long lastCompletedRegularFrameNumber, + long lastCompletedReprocessFrameNumber, + long lastCompletedZslFrameNumber) { + this(requestId, subsequenceId, afTriggerId, precaptureTriggerId, frameNumber, + partialResultCount, errorStreamId, errorPhysicalCameraId, + lastCompletedRegularFrameNumber, lastCompletedReprocessFrameNumber, + lastCompletedZslFrameNumber, + false /*hasReadOutTimestamp*/, 0 /*readoutTimestamp*/); + } @Override public int describeContents() { diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java index 754472f07d47..d64009c73401 100644 --- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java +++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java @@ -1699,7 +1699,17 @@ private MandatoryStreamCombination createUHSensorMandatoryStreamCombination( } if (isUltraHighResolution) { - sizes.add(getMaxSize(sm.getOutputSizes(formatChosen))); + Size [] outputSizes = sm.getOutputSizes(formatChosen); + Size [] highResolutionOutputSizes = + sm.getHighResolutionOutputSizes(formatChosen); + Size maxBurstSize = getMaxSizeOrNull(outputSizes); + Size maxHighResolutionSize = getMaxSizeOrNull(highResolutionOutputSizes); + Size chosenMaxSize = + maxBurstSize != null ? maxBurstSize : maxHighResolutionSize; + if (maxBurstSize != null && maxHighResolutionSize != null) { + chosenMaxSize = getMaxSize(maxBurstSize, maxHighResolutionSize); + } + sizes.add(chosenMaxSize); } else { if (formatChosen == ImageFormat.RAW_SENSOR) { // RAW_SENSOR always has MAXIMUM threshold. @@ -2101,6 +2111,21 @@ private void fillUHMandatoryStreamCombinations( return sz; } + /** + * Get the largest size by area. + * + * @param sizes an array of sizes + * + * @return Largest Size or null if sizes was null or had 0 elements + */ + public static @Nullable Size getMaxSizeOrNull(Size... sizes) { + if (sizes == null || sizes.length == 0) { + return null; + } + + return getMaxSize(sizes); + } + /** * Whether or not the hardware level reported by android.info.supportedHardwareLevel is * at least the desired one (but could be higher) diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java index 47541ca16cda..f970f04a53ee 100644 --- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java +++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java @@ -75,6 +75,7 @@ public boolean enabled(int user) { return pulseOnNotificationEnabled(user) || pulseOnLongPressEnabled(user) || alwaysOnEnabled(user) + || isAmbientTickerEnabled(user) || wakeLockScreenGestureEnabled(user) || wakeDisplayGestureEnabled(user) || pickupGestureEnabled(user) @@ -84,6 +85,11 @@ public boolean enabled(int user) { || screenOffUdfpsEnabled(user); } + /** @hide */ + public boolean isAmbientGestureEnabled(int user) { + return boolSettingDefaultOn(Settings.Secure.AMBIENT_WAKE_GESTURES, user); + } + /** @hide */ public boolean pulseOnNotificationEnabled(int user) { return boolSettingDefaultOn(Settings.Secure.DOZE_ENABLED, user) @@ -96,6 +102,11 @@ public boolean pulseOnNotificationAvailable() { && ambientDisplayAvailable(); } + /** @hide */ + public boolean isAmbientTickerEnabled(int user) { + return boolSettingDefaultOff(Settings.Secure.PULSE_ON_NEW_TRACKS, user); + } + /** @hide */ public boolean pickupGestureEnabled(int user) { return boolSetting(Settings.Secure.DOZE_PICK_UP_GESTURE, user, diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 5c1da1112e2a..f943cd26420f 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -1102,7 +1102,7 @@ public boolean isHardwareDetected() { throw e.rethrowFromSystemServer(); } } else { - Slog.w(TAG, "isFingerprintHardwareDetected(): Service not connected!"); + if (DEBUG) Slog.w(TAG, "isFingerprintHardwareDetected(): Service not connected!"); } return false; } diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java index b599028ccb9b..195e5f01dd81 100644 --- a/core/java/android/os/BaseBundle.java +++ b/core/java/android/os/BaseBundle.java @@ -450,6 +450,13 @@ private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean r } else { throw e; } + } catch (RuntimeException e) { + if (sShouldDefuse && (e.getCause() instanceof ClassNotFoundException)) { + Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e); + map.erase(); + } else { + throw e; + } } finally { mMap = map; if (recycleParcel) { diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index e06e7326a860..411b68c89a5b 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -1094,6 +1094,31 @@ public static final native void setThreadGroupAndCpuset(int tid, int group) public static final native void setProcessGroup(int pid, int group) throws IllegalArgumentException, SecurityException; + /** + * Sets the scheduling group for processes in the same cgroup.procs of uid and pid + * @hide + * @param uid The user identifier of the process to change. + * @param pid The identifier of the process to change. + * @param group The target group for this process from THREAD_GROUP_*. + * @param dex2oat_only is the cgroup apply for all or for dex2oat only. + * + * @throws IllegalArgumentException Throws IllegalArgumentException if + * tid does not exist. + * @throws SecurityException Throws SecurityException if your process does + * not have permission to modify the given thread, or to use the given + * priority. + * + * group == THREAD_GROUP_DEFAULT means to move all non-background priority + * threads to the foreground scheduling group, but to leave background + * priority threads alone. group == THREAD_GROUP_BG_NONINTERACTIVE moves all + * threads, regardless of priority, to the background scheduling group. + * group == THREAD_GROUP_FOREGROUND is not allowed. + * + * Always sets cpusets. + */ + public static final native void setCgroupProcsProcessGroup(int uid, int pid, int group, boolean dex2oat_only) + throws IllegalArgumentException, SecurityException; + /** * Freeze or unfreeze the specified process. * diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index a3b836adfc8b..4ef1226a8933 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -514,7 +514,7 @@ public static void processPackage(Context context, final Handler handler) throws IOException { String filename = packageFile.getCanonicalPath(); - if (!filename.startsWith("/data/")) { + if (!filename.startsWith("/data/") || !SystemProperties.get("persist.sys.recovery_update", "").equals("true")) { return; } @@ -629,7 +629,7 @@ public static void installPackage(Context context, File packageFile, boolean pro // If the package is on the /data partition, the package needs to // be processed (i.e. uncrypt'd). The caller specifies if that has // been done in 'processed' parameter. - if (filename.startsWith("/data/")) { + if (SystemProperties.get("persist.sys.recovery_update", "").equals("true") && filename.startsWith("/data/")) { if (processed) { if (!BLOCK_MAP_FILE.exists()) { Log.e(TAG, "Package claimed to have been processed but failed to find " @@ -672,6 +672,10 @@ public static void installPackage(Context context, File packageFile, boolean pro if (!rs.setupBcb(command)) { throw new IOException("Setup BCB failed"); } + Log.i(TAG, "Setting packageFile's read permission."); + if (!packageFile.setReadable(true, false)) { + Log.w(TAG, "Error making packageFile readable."); + } try { if (!rs.allocateSpaceForUpdate(packageFile)) { rs.clearBcb(); @@ -857,7 +861,7 @@ public static void scheduleUpdateOnBoot(Context context, File packageFile) throw // If the package is on the /data partition, use the block map file as // the package name instead. - if (filename.startsWith("/data/")) { + if (SystemProperties.get("persist.sys.recovery_update", "").equals("true") && filename.startsWith("/data/")) { filename = "@/cache/recovery/block.map"; } diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 412a33a1c124..6e625ec2c3a1 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -1452,17 +1452,8 @@ public static void initThreadDefaults(ApplicationInfo ai) { builder.penaltyDeathOnNetwork(); } - if (Build.IS_USER || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) { + if (Build.IS_USER || Build.IS_USERDEBUG || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) { // Detect nothing extra - } else if (Build.IS_USERDEBUG) { - // Detect everything in bundled apps - if (isBundledSystemApp(ai)) { - builder.detectAll(); - builder.penaltyDropBox(); - if (SystemProperties.getBoolean(VISUAL_PROPERTY, false)) { - builder.penaltyFlashScreen(); - } - } } else if (Build.IS_ENG) { // Detect everything in bundled apps if (isBundledSystemApp(ai)) { @@ -1492,16 +1483,8 @@ public static void initVmDefaults(ApplicationInfo ai) { builder.penaltyDeathOnFileUriExposure(); } - if (Build.IS_USER || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) { + if (Build.IS_USER || Build.IS_USERDEBUG || DISABLE || SystemProperties.getBoolean(DISABLE_PROPERTY, false)) { // Detect nothing extra - } else if (Build.IS_USERDEBUG) { - // Detect everything in bundled apps (except activity leaks, which - // are expensive to track) - if (isBundledSystemApp(ai)) { - builder.detectAll(); - builder.permitActivityLeaks(); - builder.penaltyDropBox(); - } } else if (Build.IS_ENG) { // Detect everything in bundled apps if (isBundledSystemApp(ai)) { @@ -2646,7 +2629,7 @@ protected IWindowManager create() { */ @UnsupportedAppUsage public static Span enterCriticalSpan(String name) { - if (Build.IS_USER) { + if (Build.IS_USER || Build.IS_USERDEBUG) { return NO_OP_SPAN; } if (name == null || name.isEmpty()) { diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java index ca3433764308..35049bbba2c4 100644 --- a/core/java/android/os/Trace.java +++ b/core/java/android/os/Trace.java @@ -161,6 +161,10 @@ private Trace() { @UnsupportedAppUsage @SystemApi(client = MODULE_LIBRARIES) public static boolean isTagEnabled(long traceTag) { + if (!Build.IS_ENG) { + return false; + } + long tags = nativeGetEnabledTags(); return (tags & traceTag) != 0; } diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java index f5f1c374b636..b3cadb3ea22b 100644 --- a/core/java/android/permission/PermissionUsageHelper.java +++ b/core/java/android/permission/PermissionUsageHelper.java @@ -118,7 +118,7 @@ private static boolean shouldShowIndicators() { private static boolean shouldShowLocationIndicator() { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - PROPERTY_LOCATION_INDICATORS_ENABLED, false); + PROPERTY_LOCATION_INDICATORS_ENABLED, true); } private static long getRecentThreshold(Long now) { diff --git a/core/java/android/preference/RingtonePreference.java b/core/java/android/preference/RingtonePreference.java index c6d8c08c9141..f2becb58721f 100644 --- a/core/java/android/preference/RingtonePreference.java +++ b/core/java/android/preference/RingtonePreference.java @@ -33,6 +33,7 @@ *

* If the user chooses the "Default" item, the saved string will be one of * {@link System#DEFAULT_RINGTONE_URI}, + * {@link System#DEFAULT_RINGTONE2_URI}, * {@link System#DEFAULT_NOTIFICATION_URI}, or * {@link System#DEFAULT_ALARM_ALERT_URI}. If the user chooses the "Silent" * item, the saved string will be an empty string. diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java index b02e123e5254..7e4ec4136268 100644 --- a/core/java/android/preference/SeekBarVolumizer.java +++ b/core/java/android/preference/SeekBarVolumizer.java @@ -117,6 +117,7 @@ public void onAudioVolumeGroupChanged(int group, int flags) { @UnsupportedAppUsage private final int mStreamType; private final int mMaxStreamVolume; + private final boolean mVoiceCapable; private boolean mAffectedByRingerMode; private boolean mNotificationOrRing; private final Receiver mReceiver = new Receiver(); @@ -188,6 +189,8 @@ public SeekBarVolumizer( if (mNotificationOrRing) { mRingerMode = mAudioManager.getRingerModeInternal(); } + mVoiceCapable = context.getResources().getBoolean( + com.android.internal.R.bool.config_voice_capable); mZenMode = mNotificationManager.getZenMode(); if (mDeviceHasProductStrategies) { @@ -269,6 +272,13 @@ private static boolean isMediaStream(int stream) { return stream == AudioManager.STREAM_MUSIC; } + private boolean isNotificationStreamSeparate() { + boolean separateNotification = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, + SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false); + return mVoiceCapable && Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.VOLUME_SEPARATE_NOTIFICATION, separateNotification ? 1 : 0) == 1; + } + public void setSeekBar(SeekBar seekBar) { if (mSeekBar != null) { mSeekBar.setOnSeekBarChangeListener(null); @@ -295,24 +305,20 @@ protected void updateSeekBar() { if (zenMuted) { mSeekBar.setProgress(mLastAudibleStreamVolume, true); } else if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) { - /** - * the first variable above is preserved and the conditions below are made explicit - * so that when user attempts to slide the notification seekbar out of vibrate the - * seekbar doesn't wrongly snap back to 0 when the streams aren't aliased - */ - if (!DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false) - || mStreamType == AudioManager.STREAM_RING - || (mStreamType == AudioManager.STREAM_NOTIFICATION && mMuted)) { - mSeekBar.setProgress(0, true); - } + mSeekBar.setProgress(0, true); + mSeekBar.setEnabled(isSeekBarEnabled()); } else if (mMuted) { mSeekBar.setProgress(0, true); } else { + mSeekBar.setEnabled(isSeekBarEnabled()); mSeekBar.setProgress(mLastProgress > -1 ? mLastProgress : mOriginalStreamVolume, true); } } + private boolean isSeekBarEnabled() { + return !(mStreamType == AudioManager.STREAM_NOTIFICATION && !isNotificationStreamSeparate()); + } + @Override public boolean handleMessage(Message msg) { switch (msg.what) { @@ -397,9 +403,6 @@ private void setStopVolumeTime() { // set the time of stop volume if ((mStreamType == AudioManager.STREAM_VOICE_CALL || mStreamType == AudioManager.STREAM_RING - || (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false) - && mStreamType == AudioManager.STREAM_NOTIFICATION) || mStreamType == AudioManager.STREAM_ALARM)) { sStopVolumeTime = java.lang.System.currentTimeMillis(); } @@ -480,7 +483,7 @@ public void revertVolume() { } public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { - if (fromTouch) { + if (fromTouch && isSeekBarEnabled()) { postSetVolume(progress); } if (mCallback != null) { @@ -685,10 +688,9 @@ public void onReceive(Context context, Intent intent) { } private void updateVolumeSlider(int streamType, int streamValue) { - final boolean streamMatch = !DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false) - && mNotificationOrRing ? isNotificationOrRing(streamType) : - streamType == mStreamType; + final boolean streamMatch = mNotificationOrRing && !isNotificationStreamSeparate() + ? isNotificationOrRing(streamType) + : (streamType == mStreamType); if (mSeekBar != null && streamMatch && streamValue != -1) { final boolean muted = mAudioManager.isStreamMute(mStreamType) || streamValue == 0; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 4c80a5924eb9..a4d7cfbb1911 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4967,6 +4967,16 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean @Readable public static final String RINGTONE = "ringtone"; + /** + * Persistent store for the system-wide default ringtone for Slot2 URI. + * + * @see #RINGTONE + * @see #DEFAULT_RINGTONE2_URI + * + */ + /** {@hide} */ + public static final String RINGTONE2 = "ringtone2"; + /** * A {@link Uri} that will point to the current default ringtone at any * given time. @@ -4977,12 +4987,27 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean */ public static final Uri DEFAULT_RINGTONE_URI = getUriFor(RINGTONE); + /** + * A {@link Uri} that will point to the current default ringtone for Slot2 + * at any given time. + * + * @see #DEFAULT_RINGTONE_URI + * + */ + /** {@hide} */ + public static final Uri DEFAULT_RINGTONE2_URI = getUriFor(RINGTONE2); + /** {@hide} */ @Readable public static final String RINGTONE_CACHE = "ringtone_cache"; /** {@hide} */ public static final Uri RINGTONE_CACHE_URI = getUriFor(RINGTONE_CACHE); + /** {@hide} */ + public static final String RINGTONE2_CACHE = "ringtone2_cache"; + /** {@hide} */ + public static final Uri RINGTONE2_CACHE_URI = getUriFor(RINGTONE2_CACHE); + /** * Persistent store for the system-wide default notification sound. * @@ -5530,6 +5555,48 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean @Readable public static final String VOLUME_KEY_CURSOR_CONTROL = "volume_key_cursor_control"; + /** + * Swipe to screenshot + * @hide + */ + public static final String SWIPE_TO_SCREENSHOT = "swipe_to_screenshot"; + + /** + * Adaptive playback + * Automatically pause media when the volume is muted and + * will resume automatically when volume is restored. + * 0 = disabled + * 1 = enabled + * @hide + */ + public static final String ADAPTIVE_PLAYBACK_ENABLED = "adaptive_playback_enabled"; + + /** + * Adaptive playback's timeout in ms + * @hide + */ + public static final String ADAPTIVE_PLAYBACK_TIMEOUT = "adaptive_playback_timeout"; + + /** + * Whether to enable or disable vibration during calls + * @hide + */ + public static final String INCALL_FEEDBACK_VIBRATE = "incall_feeedback_vibrate"; + + /** + * Whether to show the battery info on the lockscreen while charging + * @hide + */ + public static final String LOCKSCREEN_BATTERY_INFO = "lockscreen_battery_info"; + + /** + * Whether to play notification sound and vibration if screen is ON + * 0 - never + * 1 - always + * @hide + */ + public static final String NOTIFICATION_SOUND_VIB_SCREEN_ON = "notification_sound_vib_screen_on"; + /** * IMPORTANT: If you add a new public settings you also have to add it to * PUBLIC_SETTINGS below. If the new setting is hidden you have to add @@ -5537,6 +5604,74 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean * the setting value. See an example above. */ + /** + * Whether to disable qs on secure lockscreen. + * @hide + */ + public static final String SECURE_LOCKSCREEN_QS_DISABLED = "secure_lockscreen_qs_disabled"; + + /** + * Whether edge light is enabled. + * Default 0 + * @hide + */ + public static final String EDGE_LIGHT_ENABLED = "edge_light_enabled"; + + /** + * Whether to show edge light for all pulse events and not just for notifications. + * Default 0 + * @hide + */ + public static final String EDGE_LIGHT_ALWAYS_TRIGGER_ON_PULSE = "edge_light_always_trigger_on_pulse"; + + /** + * Whether to repeat edge light animation until pulse timeout. + * Default 0 + * @hide + */ + public static final String EDGE_LIGHT_REPEAT_ANIMATION = "edge_light_repeat_animation"; + + /** + * Color mode of edge light. + * 0: Accent + * 1: Notification + * 2: Wallpaper + * 3: Custom + * Default 0 + * @hide + */ + public static final String EDGE_LIGHT_COLOR_MODE = "edge_light_color_mode"; + + /** + * Custom color (hex value) for edge light. + * Default #FFFFFF + * @hide + */ + public static final String EDGE_LIGHT_CUSTOM_COLOR = "edge_light_custom_color"; + + /** + * Show app volume rows in volume panel + * @hide + */ + public static final String SHOW_APP_VOLUME = "show_app_volume"; + + /** + * Whether user can swap the order of the Alert Slider. + * * Whether user can invert the order of the Alert Slider. + * 0: Default + * 1: Inverted + * @hide + */ + public static final String ALERT_SLIDER_ORDER = "alert_slider_order"; + + /** + * Preferred silent mode for Alert Slider.. + * 0: Alarms only. + * 1: Total silence + * @hide + */ + public static final String ALERT_SLIDER_SILENT_MODE = "alert_slider_silent_mode"; + /** * Keys we no longer back up under the current schema, but want to continue to * process when restoring historical backup datasets. @@ -5549,6 +5684,12 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean public static final String[] LEGACY_RESTORE_SETTINGS = { }; + /** + * Force full screen for devices with cutout + * @hide + */ + public static final String FORCE_FULLSCREEN_CUTOUT_APPS = "force_full_screen_cutout_apps"; + /** * These are all public system settings * @@ -5588,6 +5729,7 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean PUBLIC_SETTINGS.add(VOLUME_BLUETOOTH_SCO); PUBLIC_SETTINGS.add(VOLUME_ASSISTANT); PUBLIC_SETTINGS.add(RINGTONE); + PUBLIC_SETTINGS.add(RINGTONE2); PUBLIC_SETTINGS.add(NOTIFICATION_SOUND); PUBLIC_SETTINGS.add(ALARM_ALERT); PUBLIC_SETTINGS.add(TEXT_AUTO_REPLACE); @@ -5660,6 +5802,11 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE); PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE_VENDOR_HINT); PRIVATE_SETTINGS.add(DESKTOP_MODE); + PRIVATE_SETTINGS.add(SWIPE_TO_SCREENSHOT); + PRIVATE_SETTINGS.add(ADAPTIVE_PLAYBACK_ENABLED); + PRIVATE_SETTINGS.add(ADAPTIVE_PLAYBACK_TIMEOUT); + PRIVATE_SETTINGS.add(FORCE_FULLSCREEN_CUTOUT_APPS); + PRIVATE_SETTINGS.add(INCALL_FEEDBACK_VIBRATE); } /** @@ -5692,6 +5839,7 @@ public static void getCloneToManagedProfileSettings(Set outKeySet) { public static final Map CLONE_FROM_PARENT_ON_VALUE = new ArrayMap<>(); static { CLONE_FROM_PARENT_ON_VALUE.put(RINGTONE, Secure.SYNC_PARENT_SOUNDS); + CLONE_FROM_PARENT_ON_VALUE.put(RINGTONE2, Secure.SYNC_PARENT_SOUNDS); CLONE_FROM_PARENT_ON_VALUE.put(NOTIFICATION_SOUND, Secure.SYNC_PARENT_SOUNDS); CLONE_FROM_PARENT_ON_VALUE.put(ALARM_ALERT, Secure.SYNC_PARENT_SOUNDS); } @@ -10500,7 +10648,7 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val /** * What behavior should be invoked when the volume hush gesture is triggered - * One of VOLUME_HUSH_OFF, VOLUME_HUSH_VIBRATE, VOLUME_HUSH_MUTE. + * One of VOLUME_HUSH_OFF, VOLUME_HUSH_VIBRATE, VOLUME_HUSH_MUTE, VOLUME_HUSH_CYCLE. * * @hide */ @@ -10517,6 +10665,8 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val /** @hide */ @SystemApi public static final int VOLUME_HUSH_MUTE = 2; + /** @hide */ + public static final int VOLUME_HUSH_CYCLE = 3; /** * The number of times (integer) the user has manually enabled battery saver. @@ -10954,6 +11104,26 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val */ public static final String ADAPTIVE_CONNECTIVITY_ENABLED = "adaptive_connectivity_enabled"; + /** + * Boolean value whether to separate ringtone and notification volume + * @hide + */ + public static final String VOLUME_SEPARATE_NOTIFICATION = "volume_separate_notification"; + + /** + * Whether to show ambient or lockscreen if AoD is disabled + * and we do a wake gesture like lift to wake or double tap + * + * @hide + */ + public static final String AMBIENT_WAKE_GESTURES = "ambient_wake_gestures"; + + /** + * Whether to pulse ambient on new music tracks + * @hide + */ + public static final String PULSE_ON_NEW_TRACKS = "pulse_on_new_tracks"; + /** * Keys we no longer back up under the current schema, but want to continue to * process when restoring historical backup datasets. @@ -11150,6 +11320,19 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val */ public static final String LOCK_SCREEN_WEATHER_ENABLED = "lockscreen_weather_enabled"; + /** + * Face Unlock Method + * @hide + */ + public static final String FACE_UNLOCK_METHOD = "face_unlock_method"; + + /** + * Control whether FLAG_SECURE is ignored for all windows. + * @hide + */ + @Readable + public static final String WINDOW_IGNORE_SECURE = "window_ignore_secure"; + /** * These entries are considered common between the personal and the managed profile, * since the managed profile doesn't get to change them. @@ -16104,6 +16287,18 @@ public static final class Global extends NameValueTable { CLOCKWORK_HOME_READY, }; + /** + * The amount of time in milliseconds before wifi is turned off + * @hide + */ + public static final String WIFI_OFF_TIMEOUT = "wifi_off_timeout"; + + /** + * The amount of time in milliseconds before bluetooth is turned off + * @hide + */ + public static final String BLUETOOTH_OFF_TIMEOUT = "bluetooth_off_timeout"; + /** * Keys we no longer back up under the current schema, but want to continue to * process when restoring historical backup datasets. @@ -18445,6 +18640,12 @@ private Panel() { @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_VOLUME = "android.settings.panel.action.VOLUME"; + + /** + * @hide + */ + public static final String ACTION_APP_VOLUME = + "android.settings.panel.action.APP_VOLUME"; } /** diff --git a/core/java/android/security/net/config/PinSet.java b/core/java/android/security/net/config/PinSet.java index d3c975eb3101..ff66b6c3be49 100644 --- a/core/java/android/security/net/config/PinSet.java +++ b/core/java/android/security/net/config/PinSet.java @@ -17,8 +17,10 @@ package android.security.net.config; import android.util.ArraySet; + import java.util.Collections; import java.util.Set; +import java.util.stream.Collectors; /** @hide */ public final class PinSet { @@ -26,6 +28,7 @@ public final class PinSet { new PinSet(Collections.emptySet(), Long.MAX_VALUE); public final long expirationTime; public final Set pins; + private final Set algorithms; public PinSet(Set pins, long expirationTime) { if (pins == null) { @@ -33,14 +36,12 @@ public PinSet(Set pins, long expirationTime) { } this.pins = pins; this.expirationTime = expirationTime; + this.algorithms = pins.stream() + .map(pin -> pin.digestAlgorithm) + .collect(Collectors.toCollection(ArraySet::new)); } Set getPinAlgorithms() { - // TODO: Cache this. - Set algorithms = new ArraySet(); - for (Pin pin : pins) { - algorithms.add(pin.digestAlgorithm); - } return algorithms; } } diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index 66188cd19721..fc6bca65cbbf 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -71,10 +71,13 @@ public class StatusBarNotification implements Parcelable { private Context mContext; // used for inflation & icon expansion + private boolean mIsContentSecure; + /** @hide */ public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, int initialPid, Notification notification, UserHandle user, - String overrideGroupKey, long postTime) { + String overrideGroupKey, long postTime, + boolean isContentSecure) { if (pkg == null) throw new NullPointerException(); if (notification == null) throw new NullPointerException(); @@ -90,6 +93,7 @@ public StatusBarNotification(String pkg, String opPkg, int id, this.overrideGroupKey = overrideGroupKey; this.key = key(); this.groupKey = groupKey(); + mIsContentSecure = isContentSecure; } /** @@ -137,6 +141,7 @@ public StatusBarNotification(Parcel in) { } this.key = key(); this.groupKey = groupKey(); + mIsContentSecure = in.readBoolean(); } /** @@ -237,6 +242,7 @@ public void writeToParcel(Parcel out, int flags) { } else { out.writeInt(0); } + out.writeBoolean(mIsContentSecure); } public int describeContents() { @@ -276,7 +282,8 @@ public StatusBarNotification clone() { StatusBarNotification cloneShallow(Notification notification) { StatusBarNotification result = new StatusBarNotification(this.pkg, this.opPkg, this.id, this.tag, this.uid, this.initialPid, - notification, this.user, this.overrideGroupKey, this.postTime); + notification, this.user, this.overrideGroupKey, + this.postTime, mIsContentSecure); result.setInstanceId(this.mInstanceId); return result; } @@ -550,4 +557,24 @@ private String shortenTag(String logTag) { return logTag.substring(0, MAX_LOG_TAG_LENGTH - hash.length() - 1) + "-" + hash; } + + /** + * Set whether the notification content is secure. + * + * @param isContentSecure whether the content is secure. + * @hide + */ + public void setIsContentSecure(boolean isContentSecure) { + mIsContentSecure = isContentSecure; + } + + /** + * Check whether the notification content is secure. + * + * @return true if content is secure, false otherwise. + * @hide + */ + public boolean getIsContentSecure() { + return mIsContentSecure; + } } diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java index a8aea7c1eb59..3697b9494949 100644 --- a/core/java/android/speech/tts/TtsEngines.java +++ b/core/java/android/speech/tts/TtsEngines.java @@ -498,7 +498,7 @@ static public String[] toOldLocaleStringFormat(Locale locale) { * specific preference in the list. */ private static String parseEnginePrefFromList(String prefValue, String engineName) { - if (TextUtils.isEmpty(prefValue)) { + if (TextUtils.isEmpty(prefValue) || TextUtils.isEmpty(engineName)) { return null; } diff --git a/core/java/android/util/BoostFramework.java b/core/java/android/util/BoostFramework.java new file mode 100644 index 000000000000..7110c1579215 --- /dev/null +++ b/core/java/android/util/BoostFramework.java @@ -0,0 +1,938 @@ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.util; + +import android.app.ActivityThread; +import android.content.Context; +import android.graphics.BLASTBufferQueue; +import android.os.SystemProperties; +import android.util.Log; + +import dalvik.system.PathClassLoader; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** @hide */ +public class BoostFramework { + + private static final String TAG = "BoostFramework"; + private static final String PERFORMANCE_JAR = "/system/framework/QPerformance.jar"; + private static final String PERFORMANCE_CLASS = "com.qualcomm.qti.Performance"; + + private static final String UXPERFORMANCE_JAR = "/system/framework/UxPerformance.jar"; + private static final String UXPERFORMANCE_CLASS = "com.qualcomm.qti.UxPerformance"; + public static final float PERF_HAL_V22 = 2.2f; + public static final float PERF_HAL_V23 = 2.3f; + public static final int VENDOR_T_API_LEVEL = 33; + public final int board_first_api_lvl = SystemProperties.getInt("ro.board.first_api_level", 0); + public final int board_api_lvl = SystemProperties.getInt("ro.board.api_level", 0); + +/** @hide */ + private static boolean sIsLoaded = false; + private static Class sPerfClass = null; + private static Method sAcquireFunc = null; + private static Method sPerfHintFunc = null; + private static Method sReleaseFunc = null; + private static Method sReleaseHandlerFunc = null; + private static Method sFeedbackFunc = null; + private static Method sFeedbackFuncExtn = null; + private static Method sPerfGetPropFunc = null; + private static Method sAcqAndReleaseFunc = null; + private static Method sperfHintAcqRelFunc = null; + private static Method sperfHintRenewFunc = null; + private static Method sPerfEventFunc = null; + private static Method sPerfGetPerfHalVerFunc = null; + private static Method sPerfSyncRequest = null; + + private static Method sIOPStart = null; + private static Method sIOPStop = null; + private static Method sUXEngineEvents = null; + private static Method sUXEngineTrigger = null; + + private static boolean sUxIsLoaded = false; + private static Class sUxPerfClass = null; + private static Method sUxIOPStart = null; + + private static boolean sIsSupported = false; + +/** @hide */ + private Object mPerf = null; + private Object mUxPerf = null; + + //perf hints + public static final int VENDOR_HINT_SCROLL_BOOST = 0x00001080; + public static final int VENDOR_HINT_FIRST_LAUNCH_BOOST = 0x00001081; + public static final int VENDOR_HINT_SUBSEQ_LAUNCH_BOOST = 0x00001082; + public static final int VENDOR_HINT_ANIM_BOOST = 0x00001083; + public static final int VENDOR_HINT_ACTIVITY_BOOST = 0x00001084; + public static final int VENDOR_HINT_TOUCH_BOOST = 0x00001085; + public static final int VENDOR_HINT_MTP_BOOST = 0x00001086; + public static final int VENDOR_HINT_DRAG_BOOST = 0x00001087; + public static final int VENDOR_HINT_PACKAGE_INSTALL_BOOST = 0x00001088; + public static final int VENDOR_HINT_ROTATION_LATENCY_BOOST = 0x00001089; + public static final int VENDOR_HINT_ROTATION_ANIM_BOOST = 0x00001090; + public static final int VENDOR_HINT_PERFORMANCE_MODE = 0x00001091; + public static final int VENDOR_HINT_APP_UPDATE = 0x00001092; + public static final int VENDOR_HINT_KILL = 0x00001093; + public static final int VENDOR_HINT_BOOST_RENDERTHREAD = 0x00001096; + //perf events + public static final int VENDOR_HINT_FIRST_DRAW = 0x00001042; + public static final int VENDOR_HINT_TAP_EVENT = 0x00001043; + public static final int VENDOR_HINT_DRAG_START = 0x00001051; + public static final int VENDOR_HINT_DRAG_END = 0x00001052; + //Ime Launch Boost Hint + public static final int VENDOR_HINT_IME_LAUNCH_EVENT = 0x0000109F; + + //feedback hints + public static final int VENDOR_FEEDBACK_WORKLOAD_TYPE = 0x00001601; + public static final int VENDOR_FEEDBACK_LAUNCH_END_POINT = 0x00001602; + public static final int VENDOR_FEEDBACK_PA_FW = 0x00001604; + + //UXE Events and Triggers + public static final int UXE_TRIGGER = 1; + public static final int UXE_EVENT_BINDAPP = 2; + public static final int UXE_EVENT_DISPLAYED_ACT = 3; + public static final int UXE_EVENT_KILL = 4; + public static final int UXE_EVENT_GAME = 5; + public static final int UXE_EVENT_SUB_LAUNCH = 6; + public static final int UXE_EVENT_PKG_UNINSTALL = 7; + public static final int UXE_EVENT_PKG_INSTALL = 8; + + //New Hints while porting IOP to Perf Hal. + public static final int VENDOR_HINT_BINDAPP = 0x000010A0; + public static final int VENDOR_HINT_WARM_LAUNCH = 0x000010A1; //SUB_LAUNCH + // 0x000010A2 is added in UXPerformance.java for SPEED Hints + public static final int VENDOR_HINT_PKG_INSTALL = 0x000010A3; + public static final int VENDOR_HINT_PKG_UNINSTALL = 0x000010A4; + + //perf opcodes + public static final int MPCTLV3_GPU_IS_APP_FG = 0X42820000; + public static final int MPCTLV3_GPU_IS_APP_BG = 0X42824000; + + public class Scroll { + public static final int VERTICAL = 1; + public static final int HORIZONTAL = 2; + public static final int PANEL_VIEW = 3; + public static final int PREFILING = 4; + }; + + public class Launch { + public static final int BOOST_V1 = 1; + public static final int BOOST_V2 = 2; + public static final int BOOST_V3 = 3; + public static final int BOOST_GAME = 4; + public static final int RESERVED_1 = 5; + public static final int RESERVED_2 = 6; + public static final int RESERVED_3 = 7; + public static final int RESERVED_4 = 8; + public static final int RESERVED_5 = 9; + public static final int ACTIVITY_LAUNCH_BOOST = 10; + public static final int TYPE_SERVICE_START = 100; + public static final int TYPE_START_PROC = 101; + public static final int TYPE_START_APP_FROM_BG = 102; + public static final int TYPE_ATTACH_APPLICATION = 103; + }; + + public class Draw { + public static final int EVENT_TYPE_V1 = 1; + }; + + public class WorkloadType { + public static final int NOT_KNOWN = 0; + public static final int APP = 1; + public static final int GAME = 2; + public static final int BROWSER = 3; + public static final int PREPROAPP = 4; + }; + +/** @hide */ + public BoostFramework() { + initFunctions(ActivityThread.currentActivityThread().getSystemContext()); + + try { + if (sPerfClass != null) { + mPerf = sPerfClass.newInstance(); + } + if (sUxPerfClass != null) { + mUxPerf = sUxPerfClass.newInstance(); + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_2 = " + e); + } + } + +/** @hide */ + public BoostFramework(Context context) { + this(context, false); + } + +/** @hide */ + public BoostFramework(Context context, boolean isTrusted) { + initFunctions(context); + + try { + if (sPerfClass != null) { + Constructor cons = sPerfClass.getConstructor(Context.class); + if (cons != null) + mPerf = cons.newInstance(context); + } + if (sUxPerfClass != null) { + if (isTrusted) { + Constructor cons = sUxPerfClass.getConstructor(Context.class); + if (cons != null) + mUxPerf = cons.newInstance(context); + } else { + mUxPerf = sUxPerfClass.newInstance(); + } + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_3 = " + e); + } + } + +/** @hide */ + public BoostFramework(boolean isUntrustedDomain) { + initFunctions(ActivityThread.currentActivityThread().getSystemContext()); + + try { + if (sPerfClass != null) { + Constructor cons = sPerfClass.getConstructor(boolean.class); + if (cons != null) + mPerf = cons.newInstance(isUntrustedDomain); + } + if (sUxPerfClass != null) { + mUxPerf = sUxPerfClass.newInstance(); + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_5 = " + e); + } + } + + private void initFunctions (Context context) { + sIsSupported = context.getResources().getBoolean(com.android.internal.R.bool.config_supportsBoostFramework); + + synchronized(BoostFramework.class) { + if (sIsSupported && sIsLoaded == false) { + try { + sPerfClass = Class.forName(PERFORMANCE_CLASS); + + Class[] argClasses = new Class[] {int.class, int[].class}; + sAcquireFunc = sPerfClass.getMethod("perfLockAcquire", argClasses); + + argClasses = new Class[] {int.class, String.class, int.class, int.class}; + sPerfHintFunc = sPerfClass.getMethod("perfHint", argClasses); + + argClasses = new Class[] {}; + sReleaseFunc = sPerfClass.getMethod("perfLockRelease", argClasses); + + argClasses = new Class[] {int.class}; + sReleaseHandlerFunc = sPerfClass.getDeclaredMethod("perfLockReleaseHandler", argClasses); + + argClasses = new Class[] {int.class, String.class}; + sFeedbackFunc = sPerfClass.getMethod("perfGetFeedback", argClasses); + + argClasses = new Class[] {int.class, String.class, int.class, int[].class}; + sFeedbackFuncExtn = sPerfClass.getMethod("perfGetFeedbackExtn", argClasses); + + argClasses = new Class[] {int.class, String.class, String.class}; + sIOPStart = sPerfClass.getDeclaredMethod("perfIOPrefetchStart", argClasses); + + argClasses = new Class[] {}; + sIOPStop = sPerfClass.getDeclaredMethod("perfIOPrefetchStop", argClasses); + + argClasses = new Class[] {String.class, String.class}; + sPerfGetPropFunc = sPerfClass.getMethod("perfGetProp", argClasses); + + argClasses = new Class[] {int.class, int.class, int.class, int.class, int[].class}; + sAcqAndReleaseFunc = sPerfClass.getMethod("perfLockAcqAndRelease", argClasses); + + argClasses = new Class[] {int.class, String.class, int.class, int[].class}; + sPerfEventFunc = sPerfClass.getMethod("perfEvent", argClasses); + + argClasses = new Class[] {int.class}; + sPerfSyncRequest = sPerfClass.getMethod("perfSyncRequest", argClasses); + + argClasses = new Class[] {int.class, int.class, String.class, int.class, + int.class, int.class, int[].class}; + sperfHintAcqRelFunc = sPerfClass.getMethod("perfHintAcqRel", argClasses); + + argClasses = new Class[] {int.class, int.class, String.class, int.class, + int.class, int.class, int[].class}; + sperfHintRenewFunc = sPerfClass.getMethod("perfHintRenew", argClasses); + + try { + argClasses = new Class[] {}; + sPerfGetPerfHalVerFunc = sPerfClass.getMethod("perfGetHalVer", argClasses); + + } catch (Exception e) { + Log.i(TAG, "BoostFramework() : Exception_1 = perfGetHalVer not supported"); + sPerfGetPerfHalVerFunc = null; + } + + try { + argClasses = new Class[] {int.class, int.class, String.class, int.class, String.class}; + sUXEngineEvents = sPerfClass.getDeclaredMethod("perfUXEngine_events", + argClasses); + + argClasses = new Class[] {int.class}; + sUXEngineTrigger = sPerfClass.getDeclaredMethod("perfUXEngine_trigger", + argClasses); + } catch (Exception e) { + Log.i(TAG, "BoostFramework() : Exception_4 = PreferredApps not supported"); + } + + sIsLoaded = true; + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_1 = " + e); + } + // Load UXE Class now Adding new try/catch block to avoid + // any interference with Qperformance + try { + sUxPerfClass = Class.forName(UXPERFORMANCE_CLASS); + + Class[] argUxClasses = new Class[] {int.class, String.class, String.class}; + sUxIOPStart = sUxPerfClass.getDeclaredMethod("perfIOPrefetchStart", argUxClasses); + + sUxIsLoaded = true; + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() Ux Perf: Exception = " + e); + } + } + } + } + +/** @hide */ + public int perfLockAcquire(int duration, int... list) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sAcquireFunc != null) { + Object retVal = sAcquireFunc.invoke(mPerf, duration, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockRelease() { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sReleaseFunc != null) { + Object retVal = sReleaseFunc.invoke(mPerf); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockReleaseHandler(int handle) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sReleaseHandlerFunc != null) { + Object retVal = sReleaseHandlerFunc.invoke(mPerf, handle); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfHint(int hint, String userDataStr) { + return perfHint(hint, userDataStr, -1, -1); + } + +/** @hide */ + public int perfHint(int hint, String userDataStr, int userData) { + return perfHint(hint, userDataStr, userData, -1); + } + +/** @hide */ + public int perfHint(int hint, String userDataStr, int userData1, int userData2) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sPerfHintFunc != null) { + Object retVal = sPerfHintFunc.invoke(mPerf, hint, userDataStr, userData1, userData2); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public double getPerfHalVersion() { + double retVal = PERF_HAL_V22; + if (!sIsSupported){ + return retVal; + } + try { + if (sPerfGetPerfHalVerFunc != null) { + Object ret = sPerfGetPerfHalVerFunc.invoke(mPerf); + retVal = (double)ret; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return retVal; + } + +/** @hide */ + public int perfGetFeedback(int req, String pkg_name) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sFeedbackFunc != null) { + Object retVal = sFeedbackFunc.invoke(mPerf, req, pkg_name); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfGetFeedbackExtn(int req, String pkg_name, int numArgs, int... list) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sFeedbackFuncExtn != null) { + Object retVal = sFeedbackFuncExtn.invoke(mPerf, req, pkg_name, numArgs, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfIOPrefetchStart(int pid, String pkgName, String codePath) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + Object retVal = sIOPStart.invoke(mPerf, pid, pkgName, codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + try { + Object retVal = sUxIOPStart.invoke(mUxPerf, pid, pkgName, codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Ux Perf Exception " + e); + } + + return ret; + } + +/** @hide */ + public int perfIOPrefetchStop() { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + Object retVal = sIOPStop.invoke(mPerf); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfUXEngine_events(int opcode, int pid, String pkgName, int lat) { + return perfUXEngine_events(opcode, pid, pkgName, lat, null); + } + +/** @hide */ + public int perfUXEngine_events(int opcode, int pid, String pkgName, int lat, String codePath) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sUXEngineEvents == null) { + return ret; + } + + Object retVal = sUXEngineEvents.invoke(mPerf, opcode, pid, pkgName, lat,codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + + +/** @hide */ + public String perfUXEngine_trigger(int opcode) { + String ret = null; + if (!sIsSupported){ + return ret; + } + try { + if (sUXEngineTrigger == null) { + return ret; + } + Object retVal = sUXEngineTrigger.invoke(mPerf, opcode); + ret = (String) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + +/** @hide */ + public String perfSyncRequest(int opcode) { + String ret = null; + if (!sIsSupported){ + return ret; + } + try { + if (sPerfSyncRequest == null) { + return ret; + } + Object retVal = sPerfSyncRequest.invoke(mPerf, opcode); + ret = (String) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + +/** @hide */ + public String perfGetProp(String prop_name, String def_val) { + String ret = ""; + if (!sIsSupported){ + return def_val; + } + try { + if (sPerfGetPropFunc != null) { + Object retVal = sPerfGetPropFunc.invoke(mPerf, prop_name, def_val); + ret = (String)retVal; + }else { + ret = def_val; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockAcqAndRelease(int handle, int duration, int numArgs,int reserveNumArgs, int... list) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sAcqAndReleaseFunc != null) { + Object retVal = sAcqAndReleaseFunc.invoke(mPerf, handle, duration, numArgs, reserveNumArgs, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public void perfEvent(int eventId, String pkg_name) { + perfEvent(eventId, pkg_name, 0); + } + +/** @hide */ + public void perfEvent(int eventId, String pkg_name, int numArgs, int... list) { + if (!sIsSupported){ + return; + } + try { + if (sPerfEventFunc != null) { + sPerfEventFunc.invoke(mPerf, eventId, pkg_name, numArgs, list); + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + } + +/** @hide */ + public int perfHintAcqRel(int handle, int hint, String pkg_name) { + return perfHintAcqRel(handle, hint, pkg_name, -1, -1, 0); + } + +/** @hide */ + public int perfHintAcqRel(int handle, int hint, String pkg_name, int duration) { + return perfHintAcqRel(handle, hint, pkg_name, duration, -1, 0); + } + +/** @hide */ + public int perfHintAcqRel(int handle, int hint, String pkg_name, int duration, int hintType) { + return perfHintAcqRel(handle, hint, pkg_name, duration, hintType, 0); + } + +/** @hide */ + public int perfHintAcqRel(int handle, int hint, String pkg_name, int duration, + int hintType, int numArgs, int... list) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sperfHintAcqRelFunc != null) { + Object retVal = sperfHintAcqRelFunc.invoke(mPerf,handle, hint, pkg_name, + duration, hintType, numArgs, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfHintRenew(int handle, int hint, String pkg_name) { + return perfHintRenew(handle, hint, pkg_name, -1, -1, 0); + } + +/** @hide */ + public int perfHintRenew(int handle, int hint, String pkg_name, int duration) { + return perfHintRenew(handle, hint, pkg_name, duration, -1, 0); + } + +/** @hide */ + public int perfHintRenew(int handle, int hint, String pkg_name, int duration, int hintType) { + return perfHintRenew(handle, hint, pkg_name, duration, hintType, 0); + } + +/** @hide */ + public int perfHintRenew(int handle, int hint, String pkg_name, int duration, + int hintType, int numArgs, int... list) { + int ret = -1; + if (!sIsSupported){ + return ret; + } + try { + if (sperfHintRenewFunc != null) { + Object retVal = sperfHintRenewFunc.invoke(mPerf,handle, hint, pkg_name, + duration, hintType, numArgs, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + + /** @hide */ + public static class ScrollOptimizer { + /** @hide */ + public static final int FLING_START = 1; + /** @hide */ + public static final int FLING_END = 0; + private static final String SCROLL_OPT_PROP = "ro.vendor.perf.scroll_opt"; + private static final String QXPERFORMANCE_JAR = + "/system/framework/QXPerformance.jar"; + private static final String SCROLL_OPT_CLASS = + "com.qualcomm.qti.QXPerformance.ScrollOptimizer"; + private static boolean sScrollOptProp = false; + private static boolean sScrollOptEnable = false; + private static boolean sQXIsLoaded = false; + private static Class sQXPerfClass = null; + private static Method sSetFrameInterval = null; + private static Method sDisableOptimizer = null; + private static Method sSetBLASTBufferQueue = null; + private static Method sSetMotionType = null; + private static Method sSetVsyncTime = null; + private static Method sSetUITaskStatus = null; + private static Method sSetFlingFlag = null; + private static Method sShouldUseVsync = null; + private static Method sGetFrameDelay = null; + private static Method sGetAdjustedAnimationClock = null; + + private static void initQXPerfFuncs() { + if (!sIsSupported || sQXIsLoaded) return; + + try { + sScrollOptProp = SystemProperties.getBoolean(SCROLL_OPT_PROP, false); + if (!sScrollOptProp) { + sScrollOptEnable = false; + sQXIsLoaded = true; + return; + } + + PathClassLoader qXPerfClassLoader = new PathClassLoader( + QXPERFORMANCE_JAR, ClassLoader.getSystemClassLoader()); + sQXPerfClass = qXPerfClassLoader.loadClass(SCROLL_OPT_CLASS); + Class[] argClasses = new Class[]{long.class}; + sSetFrameInterval = sQXPerfClass.getMethod( + "setFrameInterval", argClasses); + + argClasses = new Class[]{boolean.class}; + sDisableOptimizer = sQXPerfClass.getMethod("disableOptimizer", argClasses); + + argClasses = new Class[]{BLASTBufferQueue.class}; + sSetBLASTBufferQueue = sQXPerfClass.getMethod("setBLASTBufferQueue", argClasses); + + argClasses = new Class[]{int.class}; + sSetMotionType = sQXPerfClass.getMethod("setMotionType", argClasses); + + argClasses = new Class[]{long.class}; + sSetVsyncTime = sQXPerfClass.getMethod("setVsyncTime", argClasses); + + argClasses = new Class[]{boolean.class}; + sSetUITaskStatus = sQXPerfClass.getMethod("setUITaskStatus", argClasses); + + argClasses = new Class[]{int.class}; + sSetFlingFlag = sQXPerfClass.getMethod("setFlingFlag", argClasses); + + sShouldUseVsync = sQXPerfClass.getMethod("shouldUseVsync"); + + argClasses = new Class[]{long.class}; + sGetFrameDelay = sQXPerfClass.getMethod("getFrameDelay", argClasses); + + argClasses = new Class[]{long.class}; + sGetAdjustedAnimationClock = sQXPerfClass.getMethod( + "getAdjustedAnimationClock", argClasses); + } catch (Exception e) { + Log.e(TAG, "initQXPerfFuncs failed"); + e.printStackTrace(); + } finally { + // If frameworks and perf changes don't match(may not built together) + // or other exception, need to set sQXIsLoaded as true to avoid retry. + sQXIsLoaded = true; + } + } + + /** @hide */ + public static void setFrameInterval(long frameIntervalNanos) { + if (!sIsSupported){ + return; + } + if (sQXIsLoaded) { + if (sScrollOptEnable && sSetFrameInterval != null) { + try { + sSetFrameInterval.invoke(null, frameIntervalNanos); + } catch (Exception e) { + e.printStackTrace(); + } + } + return; + } + Thread initThread = new Thread(new Runnable() { + @Override + public void run() { + synchronized(ScrollOptimizer.class) { + try { + initQXPerfFuncs(); + if (sScrollOptProp && sSetFrameInterval != null) { + sSetFrameInterval.invoke(null, frameIntervalNanos); + sScrollOptEnable = true; + } + } catch (Exception e) { + Log.e(TAG, "Failed to run initThread."); + e.printStackTrace(); + } + } + } + }); + initThread.start(); + } + + /** @hide */ + public static void disableOptimizer(boolean disabled) { + if (!sIsSupported){ + return; + } + if (sScrollOptEnable && sDisableOptimizer != null) { + try { + sDisableOptimizer.invoke(null, disabled); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setBLASTBufferQueue(BLASTBufferQueue blastBufferQueue) { + if (!sIsSupported){ + return; + } + if (sScrollOptEnable && sSetBLASTBufferQueue != null) { + try { + sSetBLASTBufferQueue.invoke(null, blastBufferQueue); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setMotionType(int eventType) { + if (!sIsSupported){ + return; + } + if (sScrollOptEnable && sSetMotionType != null) { + try { + sSetMotionType.invoke(null, eventType); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setVsyncTime(long vsyncTimeNanos) { + if (!sIsSupported){ + return; + } + if (sScrollOptEnable && sSetVsyncTime != null) { + try { + sSetVsyncTime.invoke(null, vsyncTimeNanos); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setUITaskStatus(boolean running) { + if (!sIsSupported){ + return; + } + if (sScrollOptEnable && sSetUITaskStatus != null) { + try { + sSetUITaskStatus.invoke(null, running); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setFlingFlag(int flag) { + if (!sIsSupported){ + return; + } + if (sScrollOptEnable && sSetFlingFlag != null) { + try { + sSetFlingFlag.invoke(null, flag); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static boolean shouldUseVsync(boolean defaultVsyncFlag) { + boolean useVsync = defaultVsyncFlag; + if (!sIsSupported){ + return useVsync; + } + if (sScrollOptEnable && sShouldUseVsync != null) { + try { + Object retVal = sShouldUseVsync.invoke(null); + useVsync = (boolean)retVal; + } catch (Exception e) { + e.printStackTrace(); + } + } + return useVsync; + } + + /** @hide */ + public static long getFrameDelay(long defaultDelay, long lastFrameTimeNanos) { + long frameDelay = defaultDelay; + if (!sIsSupported){ + return frameDelay; + } + if (sScrollOptEnable && sGetFrameDelay != null) { + try { + Object retVal = sGetFrameDelay.invoke(null, lastFrameTimeNanos); + frameDelay = (long)retVal; + } catch (Exception e) { + e.printStackTrace(); + } + } + return frameDelay; + } + + /** @hide */ + public static long getAdjustedAnimationClock(long frameTimeNanos) { + long newFrameTimeNanos = frameTimeNanos; + if (!sIsSupported){ + return newFrameTimeNanos; + } + if (sScrollOptEnable && sGetAdjustedAnimationClock != null) { + try { + Object retVal = sGetAdjustedAnimationClock.invoke(null, + frameTimeNanos); + newFrameTimeNanos = (long)retVal; + } catch (Exception e) { + e.printStackTrace(); + } + } + return newFrameTimeNanos; + } + } +}; diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index 4654dbfa9531..a09bc6977660 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -328,15 +328,19 @@ public int hashCode() { } } - // We assume that the native methods deal with any concurrency issues. - /** * Record an event log message. * @param tag The event type tag code * @param value A value to log * @return The number of bytes written */ - public static native int writeEvent(int tag, int value); + public static int writeEvent(int tag, int value) { + if (!Build.IS_DEBUGGABLE) { + return 0; + } + + return nativeWriteEvent(tag, value); + } /** * Record an event log message. @@ -344,7 +348,13 @@ public int hashCode() { * @param value A value to log * @return The number of bytes written */ - public static native int writeEvent(int tag, long value); + public static int writeEvent(int tag, long value) { + if (!Build.IS_DEBUGGABLE) { + return 0; + } + + return nativeWriteEvent(tag, value); + } /** * Record an event log message. @@ -352,7 +362,13 @@ public int hashCode() { * @param value A value to log * @return The number of bytes written */ - public static native int writeEvent(int tag, float value); + public static int writeEvent(int tag, float value) { + if (!Build.IS_DEBUGGABLE) { + return 0; + } + + return nativeWriteEvent(tag, value); + } /** * Record an event log message. @@ -360,7 +376,13 @@ public int hashCode() { * @param str A value to log * @return The number of bytes written */ - public static native int writeEvent(int tag, String str); + public static int writeEvent(int tag, String str) { + if (!Build.IS_DEBUGGABLE) { + return 0; + } + + return nativeWriteEvent(tag, str); + } /** * Record an event log message. @@ -368,7 +390,13 @@ public int hashCode() { * @param list A list of values to log * @return The number of bytes written */ - public static native int writeEvent(int tag, Object... list); + public static int writeEvent(int tag, Object... list) { + if (!Build.IS_DEBUGGABLE) { + return 0; + } + + return nativeWriteEvent(tag, list); + } /** * Read events from the log, filtered by type. @@ -376,8 +404,14 @@ public int hashCode() { * @param output container to add events into * @throws IOException if something goes wrong reading events */ - public static native void readEvents(int[] tags, Collection output) - throws IOException; + public static void readEvents(int[] tags, Collection output) + throws IOException { + if (!Build.IS_DEBUGGABLE) { + return; + } + + nativeReadEvents(tags, output); + } /** * Read events from the log, filtered by type, blocking until logs are about to be overwritten. @@ -388,7 +422,27 @@ public static native void readEvents(int[] tags, Collection output) * @hide */ @SystemApi - public static native void readEventsOnWrapping(int[] tags, long timestamp, + public static void readEventsOnWrapping(int[] tags, long timestamp, + Collection output) + throws IOException { + if (!Build.IS_DEBUGGABLE) { + return; + } + + nativeReadEventsOnWrapping(tags, timestamp, output); + } + + // We assume that the native methods deal with any concurrency issues. + + private static native int nativeWriteEvent(int tag, int value); + private static native int nativeWriteEvent(int tag, long value); + private static native int nativeWriteEvent(int tag, float value); + private static native int nativeWriteEvent(int tag, String str); + private static native int nativeWriteEvent(int tag, Object... list); + + private static native void nativeReadEvents(int[] tags, Collection output) + throws IOException; + private static native void nativeReadEventsOnWrapping(int[] tags, long timestamp, Collection output) throws IOException; diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index c218a0ba2f49..34d8b1af0384 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -106,7 +106,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put(SETTINGS_SUPPORT_LARGE_SCREEN, "true"); DEFAULT_FLAGS.put("settings_search_always_expand", "true"); DEFAULT_FLAGS.put(SETTINGS_APP_LOCALE_OPT_IN_ENABLED, "true"); - DEFAULT_FLAGS.put(SETTINGS_VOLUME_PANEL_IN_SYSTEMUI, "false"); + DEFAULT_FLAGS.put(SETTINGS_VOLUME_PANEL_IN_SYSTEMUI, "true"); DEFAULT_FLAGS.put(SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS, "true"); DEFAULT_FLAGS.put(SETTINGS_APP_ALLOW_DARK_THEME_ACTIVATION_AT_BEDTIME, "true"); DEFAULT_FLAGS.put(SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE, "true"); diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java index d2a18dd84313..da04acedfc8d 100644 --- a/core/java/android/util/apk/ApkSignatureVerifier.java +++ b/core/java/android/util/apk/ApkSignatureVerifier.java @@ -33,8 +33,11 @@ import android.os.Build; import android.os.Trace; import android.os.incremental.V4Signature; +import android.util.ArrayMap; import android.util.Pair; +import android.util.Slog; import android.util.jar.StrictJarFile; +import android.util.BoostFramework; import com.android.internal.util.ArrayUtils; @@ -53,6 +56,9 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import java.util.zip.ZipEntry; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; /** * Facade class that takes care of the details of APK verification on @@ -64,6 +70,12 @@ public class ApkSignatureVerifier { private static final AtomicReference sBuffer = new AtomicReference<>(); + private static final String TAG = "ApkSignatureVerifier"; + // multithread verification + private static final int NUMBER_OF_CORES = + Runtime.getRuntime().availableProcessors() >= 4 ? 4 : Runtime.getRuntime().availableProcessors() ; + private static BoostFramework sPerfBoost = null; + private static boolean sIsPerfLockAcquired = false; /** * Verifies the provided APK and returns the certificates associated with each signer. */ @@ -101,6 +113,7 @@ private static ParseResult verifySignatures(ParseInput input, St * Verifies the provided APK using all allowed signing schemas. * @return the certificates associated with each signer and content digests. * @param verifyFull whether to verify all contents of this APK or just collect certificates. + * @throws PackageParserException if there was a problem collecting certificates * @hide */ public static ParseResult verifySignaturesInternal(ParseInput input, @@ -361,32 +374,45 @@ private static ParseResult verifyV2Signature(ParseInp */ private static ParseResult verifyV1Signature(ParseInput input, String apkPath, boolean verifyFull) { - StrictJarFile jarFile = null; - + int objectNumber = verifyFull ? NUMBER_OF_CORES : 1; + StrictJarFile[] jarFile = new StrictJarFile[objectNumber]; + final ArrayMap strictJarFiles = new ArrayMap(); try { final Certificate[][] lastCerts; final Signature[] lastSigs; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor"); + if (sPerfBoost == null) { + sPerfBoost = new BoostFramework(); + } + if (sPerfBoost != null && !sIsPerfLockAcquired && verifyFull) { + //Use big enough number here to hold the perflock for entire PackageInstall session + sPerfBoost.perfHint(BoostFramework.VENDOR_HINT_PACKAGE_INSTALL_BOOST, + null, Integer.MAX_VALUE, -1); + Slog.d(TAG, "Perflock acquired for PackageInstall "); + sIsPerfLockAcquired = true; + } // we still pass verify = true to ctor to collect certs, even though we're not checking // the whole jar. - jarFile = new StrictJarFile( - apkPath, - true, // collect certs - verifyFull); // whether to reject APK with stripped v2 signatures (b/27887819) + for (int i = 0; i < objectNumber; i++) { + jarFile[i] = new StrictJarFile( + apkPath, + true, // collect certs + verifyFull); // whether to reject APK with stripped v2 signatures (b/27887819) + } final List toVerify = new ArrayList<>(); // Gather certs from AndroidManifest.xml, which every APK must have, as an optimization // to not need to verify the whole APK when verifyFUll == false. - final ZipEntry manifestEntry = jarFile.findEntry( + final ZipEntry manifestEntry = jarFile[0].findEntry( ApkLiteParseUtils.ANDROID_MANIFEST_FILENAME); if (manifestEntry == null) { return input.error(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Package " + apkPath + " has no manifest"); } final ParseResult result = - loadCertificates(input, jarFile, manifestEntry); + loadCertificates(input, jarFile[0], manifestEntry); if (result.isError()) { return input.error(result); } @@ -400,7 +426,7 @@ private static ParseResult verifyV1Signature(ParseInp // fully verify all contents, except for AndroidManifest.xml and the META-INF/ files. if (verifyFull) { - final Iterator i = jarFile.iterator(); + final Iterator i = jarFile[0].iterator(); while (i.hasNext()) { final ZipEntry entry = i.next(); if (entry.isDirectory()) continue; @@ -411,30 +437,101 @@ private static ParseResult verifyV1Signature(ParseInp toVerify.add(entry); } - + class VerificationData { + public Exception exception; + public int exceptionFlag; + public boolean wait; + public int index; + public Object objWaitAll; + public boolean shutDown; + } + VerificationData vData = new VerificationData(); + vData.objWaitAll = new Object(); + final ThreadPoolExecutor verificationExecutor = new ThreadPoolExecutor( + NUMBER_OF_CORES, + NUMBER_OF_CORES, + 1,/*keep alive time*/ + TimeUnit.SECONDS, + new LinkedBlockingQueue()); for (ZipEntry entry : toVerify) { - final Certificate[][] entryCerts; - final ParseResult ret = - loadCertificates(input, jarFile, entry); - if (ret.isError()) { - return input.error(ret); - } - entryCerts = ret.getResult(); - if (ArrayUtils.isEmpty(entryCerts)) { - return input.error(INSTALL_PARSE_FAILED_NO_CERTIFICATES, - "Package " + apkPath + " has no certificates at entry " - + entry.getName()); + Runnable verifyTask = new Runnable(){ + public void run() { + try { + if (vData.exceptionFlag != 0 ) { + Slog.w(TAG, "VerifyV1 exit with exception " + vData.exceptionFlag); + return; + } + String tid = Long.toString(Thread.currentThread().getId()); + StrictJarFile tempJarFile; + synchronized (strictJarFiles) { + tempJarFile = strictJarFiles.get(tid); + if (tempJarFile == null) { + if (vData.index >= NUMBER_OF_CORES) { + vData.index = 0; + } + tempJarFile = jarFile[vData.index++]; + strictJarFiles.put(tid, tempJarFile); + } + } + final Certificate[][] entryCerts; + final ParseResult ret = + loadCertificates(input, tempJarFile, entry); + if (ret.isError()) { + throw new SecurityException(ret.getException()); + } + entryCerts = ret.getResult(); + if (ArrayUtils.isEmpty(entryCerts)) { + throw new SignatureNotFoundException("Package " + apkPath + " has no certificates at entry " + + entry.getName()); + } + + // make sure all entries use the same signing certs + final Signature[] entrySigs = convertToSignatures(entryCerts); + if (!Signature.areExactMatch(lastSigs, entrySigs)) { + throw new Exception("Package " + apkPath + " has mismatched certificates at entry " + + entry.getName()); + } + } catch (SignatureNotFoundException | SecurityException e) { + synchronized (vData.objWaitAll) { + vData.exceptionFlag = INSTALL_PARSE_FAILED_NO_CERTIFICATES; + vData.exception = e; + } + } catch (GeneralSecurityException e) { + synchronized (vData.objWaitAll) { + vData.exceptionFlag = INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; + vData.exception = e; + } + } catch (Exception e) { + synchronized (vData.objWaitAll) { + vData.exceptionFlag = INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; + vData.exception = e; + } + } + }}; + synchronized (vData.objWaitAll) { + if (vData.exceptionFlag == 0) { + verificationExecutor.execute(verifyTask); + } } - - // make sure all entries use the same signing certs - final Signature[] entrySigs = convertToSignatures(entryCerts); - if (!Signature.areExactMatch(lastSigs, entrySigs)) { - return input.error( - INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, - "Package " + apkPath + " has mismatched certificates at entry " - + entry.getName()); + } + vData.wait = true; + verificationExecutor.shutdown(); + while (vData.wait) { + try { + if (vData.exceptionFlag != 0 && !vData.shutDown) { + Slog.w(TAG, "verifyV1 Exception " + vData.exceptionFlag); + verificationExecutor.shutdownNow(); + vData.shutDown = true; + } + vData.wait = !verificationExecutor.awaitTermination(50, + TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Slog.w(TAG,"VerifyV1 interrupted while awaiting all threads done..."); } } + if (vData.exceptionFlag != 0) + return input.error(vData.exceptionFlag, + "Failed to collect certificates from " + apkPath, vData.exception); } return input.success(new SigningDetailsWithDigests( new SigningDetails(lastSigs, SignatureSchemeVersion.JAR), null)); @@ -445,8 +542,16 @@ private static ParseResult verifyV1Signature(ParseInp return input.error(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath, e); } finally { + if (sIsPerfLockAcquired && sPerfBoost != null) { + sPerfBoost.perfLockRelease(); + sIsPerfLockAcquired = false; + Slog.d(TAG, "Perflock released for PackageInstall "); + } + strictJarFiles.clear(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - closeQuietly(jarFile); + for (int i = 0; i < objectNumber ; i++) { + closeQuietly(jarFile[i]); + } } } @@ -512,9 +617,6 @@ private static void closeQuietly(StrictJarFile jarFile) { * {@code targetSdk}. */ public static int getMinimumSignatureSchemeVersionForTargetSdk(int targetSdk) { - if (targetSdk >= Build.VERSION_CODES.R) { - return SignatureSchemeVersion.SIGNING_BLOCK_V2; - } return SignatureSchemeVersion.JAR; } diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index df78827534a6..cd2ea4311264 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -804,67 +804,75 @@ public final View createView(@NonNull Context viewContext, @NonNull String name, throws ClassNotFoundException, InflateException { Objects.requireNonNull(viewContext); Objects.requireNonNull(name); - Constructor constructor = sConstructorMap.get(name); - if (constructor != null && !verifyClassLoader(constructor)) { - constructor = null; - sConstructorMap.remove(name); - } + String prefixedName = prefix != null ? (prefix + name) : name; Class clazz = null; try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, name); - if (constructor == null) { - // Class not found in the cache, see if it's real, and try to add it - clazz = Class.forName(prefix != null ? (prefix + name) : name, false, - mContext.getClassLoader()).asSubclass(View.class); - - if (mFilter != null && clazz != null) { - boolean allowed = mFilter.onLoadClass(clazz); - if (!allowed) { - failNotAllowed(name, prefix, viewContext, attrs); - } + // Opportunistically create view directly instead of using reflection + View view = tryCreateViewDirect(prefixedName, viewContext, attrs); + if (view == null) { + Constructor constructor = sConstructorMap.get(name); + if (constructor != null && !verifyClassLoader(constructor)) { + constructor = null; + sConstructorMap.remove(name); } - constructor = clazz.getConstructor(mConstructorSignature); - constructor.setAccessible(true); - sConstructorMap.put(name, constructor); - } else { - // If we have a filter, apply it to cached constructor - if (mFilter != null) { - // Have we seen this name before? - Boolean allowedState = mFilterMap.get(name); - if (allowedState == null) { - // New class -- remember whether it is allowed - clazz = Class.forName(prefix != null ? (prefix + name) : name, false, - mContext.getClassLoader()).asSubclass(View.class); - - boolean allowed = clazz != null && mFilter.onLoadClass(clazz); - mFilterMap.put(name, allowed); + + if (constructor == null) { + // Class not found in the cache, see if it's real, and try to add it + clazz = Class.forName(prefixedName, false, + mContext.getClassLoader()).asSubclass(View.class); + + if (mFilter != null && clazz != null) { + boolean allowed = mFilter.onLoadClass(clazz); if (!allowed) { failNotAllowed(name, prefix, viewContext, attrs); } - } else if (allowedState.equals(Boolean.FALSE)) { - failNotAllowed(name, prefix, viewContext, attrs); + } + constructor = clazz.getConstructor(mConstructorSignature); + constructor.setAccessible(true); + sConstructorMap.put(name, constructor); + } else { + // If we have a filter, apply it to cached constructor + if (mFilter != null) { + // Have we seen this name before? + Boolean allowedState = mFilterMap.get(name); + if (allowedState == null) { + // New class -- remember whether it is allowed + clazz = Class.forName(prefixedName, false, + mContext.getClassLoader()).asSubclass(View.class); + + boolean allowed = clazz != null && mFilter.onLoadClass(clazz); + mFilterMap.put(name, allowed); + if (!allowed) { + failNotAllowed(name, prefix, viewContext, attrs); + } + } else if (allowedState.equals(Boolean.FALSE)) { + failNotAllowed(name, prefix, viewContext, attrs); + } } } - } - Object lastContext = mConstructorArgs[0]; - mConstructorArgs[0] = viewContext; - Object[] args = mConstructorArgs; - args[1] = attrs; + Object lastContext = mConstructorArgs[0]; + mConstructorArgs[0] = viewContext; + Object[] args = mConstructorArgs; + args[1] = attrs; - try { - final View view = constructor.newInstance(args); - if (view instanceof ViewStub) { - // Use the same context when inflating ViewStub later. - final ViewStub viewStub = (ViewStub) view; - viewStub.setLayoutInflater(cloneInContext((Context) args[0])); + try { + view = constructor.newInstance(args); + } finally { + mConstructorArgs[0] = lastContext; } - return view; - } finally { - mConstructorArgs[0] = lastContext; } + + if (view instanceof ViewStub) { + // Use the same context when inflating ViewStub later. + final ViewStub viewStub = (ViewStub) view; + viewStub.setLayoutInflater(cloneInContext((Context) viewContext)); + } + + return view; } catch (NoSuchMethodException e) { final InflateException ie = new InflateException( getParserStateDescription(viewContext, attrs) @@ -1363,4 +1371,121 @@ protected void dispatchDraw(Canvas canvas) { } } } + + // Some of the views included here are deprecated, but apps still use them. + @SuppressWarnings("deprecation") + private static View tryCreateViewDirect(String name, Context context, AttributeSet attributeSet) { + // This contains all the framework views used in a set of 113 real-world apps, sorted by + // number of occurrences. While views with only 1 occurrence are unlikely to be worth + // optimizing, it doesn't hurt to include them because switch-case is compiled into a table + // lookup after calling String#hashCode(). + switch (name) { + case "android.widget.LinearLayout": // 13486 occurrences + return new android.widget.LinearLayout(context, attributeSet); + case "android.widget.View": // 6930 occurrences + case "android.webkit.View": // 63 occurrences + case "android.view.View": // 63 occurrences + case "android.app.View": // 62 occurrences + return new android.view.View(context, attributeSet); + case "android.widget.FrameLayout": // 6447 occurrences + return new android.widget.FrameLayout(context, attributeSet); + case "android.widget.ViewStub": // 5613 occurrences + case "android.view.ViewStub": // 228 occurrences + case "android.app.ViewStub": // 227 occurrences + case "android.webkit.ViewStub": // 226 occurrences + return new android.view.ViewStub(context, attributeSet); + case "android.widget.TextView": // 4722 occurrences + return new android.widget.TextView(context, attributeSet); + case "android.widget.ImageView": // 3044 occurrences + return new android.widget.ImageView(context, attributeSet); + case "android.widget.RelativeLayout": // 2665 occurrences + return new android.widget.RelativeLayout(context, attributeSet); + case "android.widget.Space": // 1694 occurrences + return new android.widget.Space(context, attributeSet); + case "android.widget.ProgressBar": // 770 occurrences + return new android.widget.ProgressBar(context, attributeSet); + case "android.widget.Button": // 382 occurrences + return new android.widget.Button(context, attributeSet); + case "android.widget.ImageButton": // 265 occurrences + return new android.widget.ImageButton(context, attributeSet); + case "android.widget.Switch": // 145 occurrences + return new android.widget.Switch(context, attributeSet); + case "android.widget.DateTimeView": // 117 occurrences + return new android.widget.DateTimeView(context, attributeSet); + case "android.widget.Toolbar": // 86 occurrences + return new android.widget.Toolbar(context, attributeSet); + case "android.widget.HorizontalScrollView": // 68 occurrences + return new android.widget.HorizontalScrollView(context, attributeSet); + case "android.widget.ScrollView": // 67 occurrences + return new android.widget.ScrollView(context, attributeSet); + case "android.widget.NotificationHeaderView": // 65 occurrences + case "android.webkit.NotificationHeaderView": // 65 occurrences + case "android.view.NotificationHeaderView": // 65 occurrences + case "android.app.NotificationHeaderView": // 65 occurrences + return new android.view.NotificationHeaderView(context, attributeSet); + case "android.widget.ListView": // 58 occurrences + return new android.widget.ListView(context, attributeSet); + case "android.widget.QuickContactBadge": // 50 occurrences + return new android.widget.QuickContactBadge(context, attributeSet); + case "android.widget.SeekBar": // 40 occurrences + return new android.widget.SeekBar(context, attributeSet); + case "android.widget.CheckBox": // 38 occurrences + return new android.widget.CheckBox(context, attributeSet); + case "android.widget.GridLayout": // 16 occurrences + return new android.widget.GridLayout(context, attributeSet); + case "android.widget.TableRow": // 15 occurrences + return new android.widget.TableRow(context, attributeSet); + case "android.widget.RadioGroup": // 15 occurrences + return new android.widget.RadioGroup(context, attributeSet); + case "android.widget.Chronometer": // 15 occurrences + return new android.widget.Chronometer(context, attributeSet); + case "android.widget.ViewFlipper": // 13 occurrences + return new android.widget.ViewFlipper(context, attributeSet); + case "android.widget.Spinner": // 9 occurrences + return new android.widget.Spinner(context, attributeSet); + case "android.widget.ViewSwitcher": // 8 occurrences + return new android.widget.ViewSwitcher(context, attributeSet); + case "android.widget.TextSwitcher": // 8 occurrences + return new android.widget.TextSwitcher(context, attributeSet); + case "android.widget.SurfaceView": // 8 occurrences + case "android.webkit.SurfaceView": // 1 occurrence + case "android.view.SurfaceView": // 1 occurrence + case "android.app.SurfaceView": // 1 occurrence + return new android.view.SurfaceView(context, attributeSet); + case "android.widget.CheckedTextView": // 8 occurrences + return new android.widget.CheckedTextView(context, attributeSet); + case "android.preference.PreferenceFrameLayout": // 8 occurrences + return new android.preference.PreferenceFrameLayout(context, attributeSet); + case "android.widget.TwoLineListItem": // 7 occurrences + return new android.widget.TwoLineListItem(context, attributeSet); + case "android.widget.TableLayout": // 5 occurrences + return new android.widget.TableLayout(context, attributeSet); + case "android.widget.EditText": // 5 occurrences + return new android.widget.EditText(context, attributeSet); + case "android.widget.TabWidget": // 3 occurrences + return new android.widget.TabWidget(context, attributeSet); + case "android.widget.TabHost": // 3 occurrences + return new android.widget.TabHost(context, attributeSet); + case "android.widget.ZoomButton": // 2 occurrences + return new android.widget.ZoomButton(context, attributeSet); + case "android.widget.TextureView": // 2 occurrences + case "android.webkit.TextureView": // 2 occurrences + case "android.app.TextureView": // 2 occurrences + case "android.view.TextureView": // 2 occurrences + return new android.view.TextureView(context, attributeSet); + case "android.widget.ExpandableListView": // 2 occurrences + return new android.widget.ExpandableListView(context, attributeSet); + case "android.widget.ViewAnimator": // 1 occurrence + return new android.widget.ViewAnimator(context, attributeSet); + case "android.widget.TextClock": // 1 occurrence + return new android.widget.TextClock(context, attributeSet); + case "android.widget.AutoCompleteTextView": // 1 occurrence + return new android.widget.AutoCompleteTextView(context, attributeSet); + case "android.widget.WebView": // 1 occurrence + case "android.webkit.WebView": // 1 occurrence + return new android.webkit.WebView(context, attributeSet); + } + + return null; + } } diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index 638b8f9f9b40..4a5989ed4e47 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -243,7 +243,7 @@ public class ViewConfiguration { * The coefficient of friction applied to flings/scrolls. */ @UnsupportedAppUsage - private static final float SCROLL_FRICTION = 0.015f; + private static final float SCROLL_FRICTION = 0.012f; /** * Max distance in dips to overscroll for edge effects diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index f6211fd488d8..540806d3f065 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -6773,6 +6773,10 @@ private int processPointerEvent(QueuedInputEvent q) { final MotionEvent event = (MotionEvent)q.mEvent; mHandwritingInitiator.onTouchEvent(event); + if (event.getPointerCount() == 3 && isSwipeToScreenshotGestureActive()) { + event.setAction(MotionEvent.ACTION_CANCEL); + } + mAttachInfo.mUnbufferedDispatchRequested = false; mAttachInfo.mHandlingPointerEvent = true; boolean handled = mView.dispatchPointerEvent(event); @@ -11334,4 +11338,12 @@ void mergeSync(int syncId, SurfaceSyncer otherSyncer) { } mSurfaceSyncer.merge(mSyncId, syncId, otherSyncer); } + + private boolean isSwipeToScreenshotGestureActive() { + try { + return ActivityManager.getService().isSwipeToScreenshotGestureActive(); + } catch (RemoteException e) { + return false; + } + } } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 293f9082670d..77135d671376 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; +import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.annotation.ColorInt; @@ -50,6 +51,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.provider.Settings; import android.transition.Scene; import android.transition.Transition; import android.transition.TransitionManager; @@ -1279,6 +1281,10 @@ public void clearFlags(int flags) { * @see #clearFlags */ public void setFlags(int flags, int mask) { + if ((mask & FLAG_SECURE) != 0 && Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.WINDOW_IGNORE_SECURE, 0) == 1) { + mask &= ~FLAG_SECURE; + } final WindowManager.LayoutParams attrs = getAttributes(); attrs.flags = (attrs.flags&~mask) | (flags&mask); mForcedWindowFlags |= mask; diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index d37756551db3..ae9a1220a246 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -32,6 +32,7 @@ import android.os.SystemProperties; import android.util.AndroidRuntimeException; import android.util.ArraySet; +import android.util.BoostFramework.ScrollOptimizer; import android.util.Log; import android.view.inputmethod.InputMethodManager; @@ -362,10 +363,12 @@ public void addView(View view, ViewGroup.LayoutParams params, // The previous removeView() had not completed executing. Now it has. } + boolean isSubWindow = false; // If this is a panel window, then find the window it is being // attached to for future reference. if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { + isSubWindow = true; final int count = mViews.size(); for (int i = 0; i < count; i++) { if (mRoots.get(i).mWindow.asBinder() == wparams.token) { @@ -396,6 +399,19 @@ public void addView(View view, ViewGroup.LayoutParams params, view.setLayoutParams(wparams); + int visibleRootCount = 0; + if (!isSubWindow) { + for (int i = mRoots.size() - 1; i >= 0; --i) { + View root_view = mRoots.get(i).getView(); + if (root_view != null && root_view.getVisibility() == View.VISIBLE) { + visibleRootCount++; + } + } + } + if (isSubWindow || visibleRootCount > 1) { + ScrollOptimizer.disableOptimizer(true); + } + mViews.add(view); mRoots.add(root); mParams.add(wparams); @@ -522,6 +538,18 @@ void doRemoveView(ViewRootImpl root) { final View view = mViews.remove(index); mDyingViews.remove(view); } + + int visibleRootCount = 0; + for (int i = mRoots.size() - 1; i >= 0; --i) { + View root_view = mRoots.get(i).getView(); + if (root_view != null && root_view.getVisibility() == View.VISIBLE) { + visibleRootCount++; + } + } + if (visibleRootCount == 1) { + ScrollOptimizer.disableOptimizer(false); + } + allViewsRemoved = mRoots.isEmpty(); } if (ThreadedRenderer.sTrimForeground) { diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index b5a742bfb2eb..ef4a77a04fd8 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -73,6 +73,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.text.style.SuggestionSpan; +import android.util.BoostFramework; import android.util.Log; import android.util.Pools.Pool; import android.util.Pools.SimplePool; @@ -282,6 +283,11 @@ public final class InputMethodManager { */ private static final String SUBTYPE_MODE_VOICE = "voice"; + //Perf + static BoostFramework mPerfBoost = null; + static boolean IME_BOOST_ENABLED = false; + static boolean isImeBoostPropertyRead = false; + /** * Provide this to {@link IInputMethodManager#startInputOrWindowGainedFocus( * int, IInputMethodClient, IBinder, int, int, int, EditorInfo, IInputContext, int)} to receive @@ -657,6 +663,20 @@ public boolean startInput(@StartInputReason int startInputReason, View focusedVi ImeTracing.getInstance().triggerClientDump( "InputMethodManager.DelegateImpl#startInput", InputMethodManager.this, null /* icProto */); + + if (isImeBoostPropertyRead == false) { + mPerfBoost = new BoostFramework(); + + if (mPerfBoost != null) { + IME_BOOST_ENABLED = Boolean.parseBoolean(mPerfBoost.perfGetProp("ro.vendor.qti.sys.fw.use_ime_boost", "false")); + } + isImeBoostPropertyRead = true; + } + + if (IME_BOOST_ENABLED == true && mPerfBoost != null) { + mPerfBoost.perfEvent(BoostFramework.VENDOR_HINT_IME_LAUNCH_EVENT, null); + } + synchronized (mH) { mCurrentTextBoxAttribute = null; mCompletions = null; diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 0b0bfb1ddbe9..3bca7f39c21e 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -684,6 +684,7 @@ public abstract class AbsListView extends AdapterView implements Te private int mMinimumVelocity; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051740) private int mMaximumVelocity; + private int mDecacheThreshold; private float mVelocityScale = 1.0f; final boolean[] mIsScrap = new boolean[1]; @@ -994,6 +995,7 @@ private void initAbsListView() { mVerticalScrollFactor = configuration.getScaledVerticalScrollFactor(); mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + mDecacheThreshold = mMaximumVelocity / 2; mOverscrollDistance = configuration.getScaledOverscrollDistance(); mOverflingDistance = configuration.getScaledOverflingDistance(); @@ -4811,7 +4813,7 @@ public void run() { // Keep the fling alive a little longer postDelayed(this, FLYWHEEL_TIMEOUT); } else { - endFling(); + endFling(false); // Don't disable the scrolling cache right after it was enabled mTouchMode = TOUCH_MODE_SCROLL; reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); } @@ -4822,11 +4824,17 @@ public void run() { FlingRunnable() { mScroller = new OverScroller(getContext()); + mScroller.setFriction(0.006f); } // Use AbsListView#fling(int) instead @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) void start(int initialVelocity) { + if (Math.abs(initialVelocity) > mDecacheThreshold) { + // For long flings, scrolling cache causes stutter, so don't use it + clearScrollingCache(); + } + int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0; mLastFlingY = initialY; mScroller.setInterpolator(null); @@ -4907,6 +4915,10 @@ void startScroll(int distance, int duration, boolean linear, // To interrupt a fling early you should use smoothScrollBy(0,0) instead @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) void endFling() { + endFling(true); + } + + void endFling(boolean clearCache) { mTouchMode = TOUCH_MODE_REST; removeCallbacks(this); @@ -4915,7 +4927,8 @@ void endFling() { if (!mSuppressIdleStateChangeCall) { reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); } - clearScrollingCache(); + if (clearCache) + clearScrollingCache(); mScroller.abortAnimation(); if (mFlingStrictSpan != null) { diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java index 1683878cd8b2..93dbfa07fc4c 100644 --- a/core/java/android/widget/OverScroller.java +++ b/core/java/android/widget/OverScroller.java @@ -20,6 +20,7 @@ import android.content.Context; import android.hardware.SensorManager; import android.os.Build; +import android.util.BoostFramework.ScrollOptimizer; import android.util.Log; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; @@ -361,6 +362,7 @@ public void startScroll(int startX, int startY, int dx, int dy) { * @param duration Duration of the scroll in milliseconds. */ public void startScroll(int startX, int startY, int dx, int dy, int duration) { + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_END); mMode = SCROLL_MODE; mScrollerX.startScroll(startX, dx, duration); mScrollerY.startScroll(startY, dy, duration); diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 15cd17b20f4f..e3e86974bd0f 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -349,6 +349,7 @@ public int getMaxScrollAmount() { private void initScrollView() { mScroller = new OverScroller(getContext()); + mScroller.setFriction(0.006f); setFocusable(true); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); setWillNotDraw(false); diff --git a/core/java/com/android/internal/app/ActivityTrigger.java b/core/java/com/android/internal/app/ActivityTrigger.java new file mode 100644 index 000000000000..dbcb13f49ef5 --- /dev/null +++ b/core/java/com/android/internal/app/ActivityTrigger.java @@ -0,0 +1,101 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package com.android.internal.app; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.util.Log; + +public class ActivityTrigger +{ + private static final String TAG = "ActivityTrigger"; + + /** @hide */ + public ActivityTrigger() { + //Log.d(TAG, "ActivityTrigger initialized"); + } + + /** @hide */ + protected void finalize() { + native_at_deinit(); + } + + /** @hide */ + public void activityStartTrigger(ApplicationInfo appInfo, int pid) { + int reserved =0; + String activity = null; + activity = appInfo.packageName + "/" + appInfo.processName + "/" + + appInfo.longVersionCode + "/" + pid; + native_at_startApp(activity, reserved); + } + + /** @hide */ + public void activityResumeTrigger(Intent intent, ActivityInfo acInfo, + ApplicationInfo appInfo, boolean IsInFullScreen) { + ComponentName cn = intent.getComponent(); + String activity = null; + + if (cn != null) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_resumeActivity(activity); + } + + public void activityPauseTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { + ComponentName cn = intent.getComponent(); + String activity = null; + Log.d(TAG, "ActivityTrigger activityPauseTrigger "); + if (null != cn && null != appInfo) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_pauseActivity(activity); + } + + public void activityStopTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { + ComponentName cn = intent.getComponent(); + String activity = null; + Log.d(TAG, "ActivityTrigger activityStopTrigger "); + if (null != cn && null != appInfo) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_stopActivity(activity); + } + + public float activityMiscTrigger(int func, String activity, int flag, int type) { + return native_at_miscActivity(func, activity, flag, type); + } + + private native int native_at_startActivity(String activity, int flags); + private native int native_at_startApp(String activity, int flags); + private native void native_at_resumeActivity(String activity); + private native void native_at_pauseActivity(String activity); + private native void native_at_stopActivity(String activity); + private native void native_at_deinit(); + private native float native_at_miscActivity(int func, String activity, int flag, int type); +} diff --git a/core/java/com/android/internal/app/LogAccessDialogActivity.java b/core/java/com/android/internal/app/LogAccessDialogActivity.java index 4adb8673084b..5aae37e408d6 100644 --- a/core/java/com/android/internal/app/LogAccessDialogActivity.java +++ b/core/java/com/android/internal/app/LogAccessDialogActivity.java @@ -186,7 +186,8 @@ private String getTitleString(Context context, String callingPackage, int uid) private Spannable styleFont(String text) { Spannable s = (Spannable) Html.fromHtml(text); for (URLSpan span : s.getSpans(0, s.length(), URLSpan.class)) { - TypefaceSpan typefaceSpan = new TypefaceSpan("google-sans"); + TypefaceSpan typefaceSpan = new TypefaceSpan( + getResources().getString(com.android.internal.R.string.config_bodyFontFamily)); s.setSpan(typefaceSpan, s.getSpanStart(span), s.getSpanEnd(span), 0); } return s; diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java index 681b46a01c8d..89e6d1f50307 100644 --- a/core/java/com/android/internal/notification/SystemNotificationChannels.java +++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java @@ -113,7 +113,7 @@ public static void createAll(Context context) { final NotificationChannel developerImportant = new NotificationChannel( DEVELOPER_IMPORTANT, context.getString(R.string.notification_channel_developer_important), - NotificationManager.IMPORTANCE_HIGH); + NotificationManager.IMPORTANCE_MIN); developer.setBlockable(true); channelsList.add(developerImportant); diff --git a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java index c801be0ce3e7..4e5fb4207047 100644 --- a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java +++ b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.Build; import android.os.StrictMode; import android.util.IntArray; import android.util.Slog; @@ -530,7 +531,11 @@ void readDeltaImpl(@Nullable Callback cb, boolean forceRead) { CharBuffer buf; while ((buf = iter.nextLine()) != null) { if (asLongs(buf, mBuffer) != mBuffer.length) { - Slog.wtf(mTag, "Invalid line: " + buf.toString()); + if (Build.IS_DEBUGGABLE) { + Slog.wtf(mTag, "Invalid line: " + buf.toString()); + } else { + Slog.w(mTag, "Invalid line: " + buf.toString()); + } continue; } processUidDelta(cb); diff --git a/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java b/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java index a03bac45d14f..90ad34d6924f 100644 --- a/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java +++ b/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java @@ -87,6 +87,10 @@ private static boolean allowClassLoaderCreation(String path, boolean isTestOnly) if (isTestOnly) { return true; } + // If system server is being profiled, it's OK to create class loaders anytime. + if (ZygoteInit.shouldProfileSystemServer()) { + return true; + } return false; } diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index ca1ae194cb12..66b7430db7cc 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -187,6 +187,12 @@ private static void preloadSharedLibraries() { System.loadLibrary("android"); System.loadLibrary("compiler_rt"); System.loadLibrary("jnigraphics"); + + try { + System.loadLibrary("qti_performance"); + } catch (UnsatisfiedLinkError e) { + Log.e(TAG, "Couldn't load qti_performance"); + } } native private static void nativePreloadAppProcessHALs(); @@ -238,6 +244,21 @@ private static void warmUpJcaProviders() { Trace.traceEnd(Trace.TRACE_TAG_DALVIK); } + private static boolean isExperimentEnabled(String experiment) { + boolean defaultValue = SystemProperties.getBoolean( + "dalvik.vm." + experiment, + /*def=*/false); + // Can't use device_config since we are the zygote, and it's not initialized at this point. + return SystemProperties.getBoolean( + "persist.device_config." + DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT + + "." + experiment, + defaultValue); + } + + /* package-private */ static boolean shouldProfileSystemServer() { + return isExperimentEnabled("profilesystemserver"); + } + /** * Performs Zygote process initialization. Loads and initializes commonly used classes. * @@ -341,14 +362,7 @@ private static void preloadClasses() { // If we are profiling the boot image, reset the Jit counters after preloading the // classes. We want to preload for performance, and we can use method counters to // infer what clases are used after calling resetJitCounters, for profile purposes. - // Can't use device_config since we are the zygote. - String prop = SystemProperties.get( - "persist.device_config.runtime_native_boot.profilebootclasspath", ""); - // Might be empty if the property is unset since the default is "". - if (prop.length() == 0) { - prop = SystemProperties.get("dalvik.vm.profilebootclasspath", ""); - } - if ("true".equals(prop)) { + if (isExperimentEnabled("profilebootclasspath")) { Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ResetJitCounters"); VMRuntime.resetJitCounters(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); @@ -489,16 +503,6 @@ private static void gcAndFinalize() { ZygoteHooks.gcAndFinalize(); } - private static boolean shouldProfileSystemServer() { - boolean defaultValue = SystemProperties.getBoolean("dalvik.vm.profilesystemserver", - /*default=*/ false); - // Can't use DeviceConfig since it's not initialized at this point. - return SystemProperties.getBoolean( - "persist.device_config." + DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT - + ".profilesystemserver", - defaultValue); - } - /** * Finish remaining work for the newly forked system server process. */ @@ -580,6 +584,13 @@ private static ClassLoader getOrCreateSystemServerClassLoader() { * in the forked system server process in the zygote SELinux domain. */ private static void prefetchStandaloneSystemServerJars() { + if (shouldProfileSystemServer()) { + // We don't prefetch AOT artifacts if we are profiling system server, as we are going to + // JIT it. + // This method only gets called from native and should already be skipped if we profile + // system server. Still, be robust and check it again. + return; + } String envStr = Os.getenv("STANDALONE_SYSTEMSERVER_JARS"); if (TextUtils.isEmpty(envStr)) { return; diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index e603e2ed57f1..f6c3b473795e 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -31,6 +31,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; @@ -2567,6 +2568,16 @@ protected ViewGroup generateLayout(DecorView decor) { params.layoutInDisplayCutoutMode = mode; } + if (ActivityManager.isSystemReady()) { + try { + String packageName = context.getBasePackageName(); + if (ActivityManager.getService().shouldForceCutoutFullscreen(packageName)){ + params.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } + } catch (RemoteException e) { + } + } + if (mAlwaysReadCloseOnTouchAttr || getContext().getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) { if (a.getBoolean( diff --git a/core/java/com/android/internal/util/HastebinException.java b/core/java/com/android/internal/util/HastebinException.java new file mode 100644 index 000000000000..417d29714ce9 --- /dev/null +++ b/core/java/com/android/internal/util/HastebinException.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 Potato Open Sauce 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.internal.util; + +public class HastebinException extends Exception { + + private static final long serialVersionUID = 666L; + + public HastebinException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/core/java/com/android/internal/util/HastebinUtils.java b/core/java/com/android/internal/util/HastebinUtils.java new file mode 100644 index 000000000000..898ee700ed2d --- /dev/null +++ b/core/java/com/android/internal/util/HastebinUtils.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2018 Potato Open Sauce 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.internal.util; + +import android.os.Handler; +import android.os.HandlerThread; +import android.util.JsonReader; + +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.URL; + +import javax.net.ssl.HttpsURLConnection; + +/** + * Helper functions for uploading to Hastebin + */ +public final class HastebinUtils { + private static final String TAG = "HastebinUtils"; + private static final String BASE_URL = "https://hastebin.com"; + private static final String API_URL = String.format("%s/documents", BASE_URL); + private static Handler handler; + + private HastebinUtils() { + } + + /** + * Uploads {@code content} to Hastebin + * + * @param content the content to upload to Hastebin + * @param callback the callback to call on success / failure + */ + public static void upload(String content, UploadResultCallback callback) { + getHandler().post(new Runnable() { + @Override + public void run() { + try { + HttpsURLConnection urlConnection = (HttpsURLConnection) new URL(API_URL).openConnection(); + try { + urlConnection.setRequestProperty("Accept-Charset", "UTF-8"); + urlConnection.setDoOutput(true); + + try (OutputStream output = urlConnection.getOutputStream()) { + output.write(content.getBytes("UTF-8")); + } + String key = ""; + try (JsonReader reader = new JsonReader( + new InputStreamReader(urlConnection.getInputStream(), "UTF-8"))) { + reader.beginObject(); + while (reader.hasNext()) { + String name = reader.nextName(); + if (name.equals("key")) { + key = reader.nextString(); + break; + } else { + reader.skipValue(); + } + } + reader.endObject(); + } + if (!key.isEmpty()) { + callback.onSuccess(getUrl(key)); + } else { + String msg = "Failed to upload to Hastebin: No key retrieved"; + callback.onFail(msg, new HastebinException(msg)); + } + } finally { + urlConnection.disconnect(); + } + } catch (Exception e) { + callback.onFail("Failed to upload to Hastebin", e); + } + } + }); + } + + /** + * Get the view URL from a key + */ + private static String getUrl(String key) { + return String.format("%s/%s", BASE_URL, key); + } + + private static Handler getHandler() { + if (handler == null) { + HandlerThread handlerThread = new HandlerThread("HastebinThread"); + if (!handlerThread.isAlive()) + handlerThread.start(); + handler = new Handler(handlerThread.getLooper()); + } + return handler; + } + + public interface UploadResultCallback { + void onSuccess(String url); + + void onFail(String message, Exception e); + } +} diff --git a/core/java/com/android/internal/util/custom/PixelPropsUtils.java b/core/java/com/android/internal/util/custom/PixelPropsUtils.java new file mode 100644 index 000000000000..e5fbe81ee831 --- /dev/null +++ b/core/java/com/android/internal/util/custom/PixelPropsUtils.java @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2022 The Pixel Experience Project + * 2021-2022 crDroid Android Project + * (C) 2023 ArrowOS + * (C) 2023 The LibreMobileOS Foundation + * + * 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.internal.util.custom; + +import android.app.ActivityTaskManager; +import android.app.Application; +import android.app.TaskStackListener; +import android.content.ComponentName; +import android.content.Context; +import android.os.Binder; +import android.os.Build; +import android.os.Process; +import android.os.SystemProperties; +import android.util.Log; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class PixelPropsUtils { + + private static final String TAG = PixelPropsUtils.class.getSimpleName(); + private static final String DEVICE = "ro.havoc.device"; + + private static final String PACKAGE_GMS = "com.google.android.gms"; + private static final ComponentName GMS_ADD_ACCOUNT_ACTIVITY = ComponentName.unflattenFromString( + "com.google.android.gms/.auth.uiflows.minutemaid.MinuteMaidActivity"); + + private static final boolean DEBUG = false; + + private static final Map propsToChangeGeneric; + private static final Map propsToChangePixel7Pro; + private static final Map propsToChangePixel6Pro; + private static final Map propsToChangePixel5; + private static final Map propsToChangePixelXL; + private static final Map> propsToKeep; + + private static final String[] packagesToChangePixel7Pro = { + "com.google.android.apps.privacy.wildlife", + "com.google.android.apps.wallpaper.pixel", + "com.google.android.apps.wallpaper", + "com.google.android.apps.subscriptions.red", + "com.google.pixel.livewallpaper" + }; + + private static final String[] packagesToChangePixel6Pro = { + "com.google.android.inputmethod.latin", + "com.google.android.as", + "com.google.android.wallpaper.effects", + "com.google.android.apps.emojiwallpaper", + }; + + private static final String[] packagesToChangePixelXL = { + "com.snapchat.android" + }; + + private static final String[] extraPackagesToChange = { + "com.android.chrome", + "com.breel.wallpapers20", + "com.nhs.online.nhsonline", + "com.netflix.mediaclient", + "com.nothing.smartcenter" + }; + + private static final String[] packagesToKeep = { + "com.google.android.dialer", + "com.google.android.euicc", + "com.google.ar.core", + "com.google.android.youtube", + "com.google.android.apps.youtube.kids", + "com.google.android.apps.youtube.music", + "com.google.android.apps.recorder", + "com.google.android.apps.wearables.maestro.companion", + "com.google.android.apps.tachyon", + "com.google.android.apps.tycho" + }; + + private static final String[] customGoogleCameraPackages = { + "com.google.android.MTCL83", + "com.google.android.UltraCVM", + "com.google.android.apps.cameralite" + }; + + // Codenames for currently supported Pixels by Google + private static final String[] pixelCodenames = { + "felix", + "tangorpro", + "lynx", + "cheetah", + "panther", + "bluejay", + "oriole", + "raven", + "barbet", + "redfin", + "bramble", + "sunfish" + }; + + private static volatile boolean sIsGms, sIsFinsky, sIsPhotos; + + static { + propsToKeep = new HashMap<>(); + propsToKeep.put("com.google.android.settings.intelligence", new ArrayList<>(Collections.singletonList("FINGERPRINT"))); + propsToChangeGeneric = new HashMap<>(); + propsToChangeGeneric.put("TYPE", "user"); + propsToChangeGeneric.put("TAGS", "release-keys"); + propsToChangePixel7Pro = new HashMap<>(); + propsToChangePixel7Pro.put("BRAND", "google"); + propsToChangePixel7Pro.put("MANUFACTURER", "Google"); + propsToChangePixel7Pro.put("DEVICE", "cheetah"); + propsToChangePixel7Pro.put("PRODUCT", "cheetah"); + propsToChangePixel7Pro.put("MODEL", "Pixel 7 Pro"); + propsToChangePixel7Pro.put("FINGERPRINT", "google/cheetah/cheetah:13/TQ3A.230705.001.A1/10217028:user/release-keys"); + propsToChangePixel6Pro = new HashMap<>(); + propsToChangePixel6Pro.put("BRAND", "google"); + propsToChangePixel6Pro.put("MANUFACTURER", "Google"); + propsToChangePixel6Pro.put("DEVICE", "raven"); + propsToChangePixel6Pro.put("PRODUCT", "raven"); + propsToChangePixel6Pro.put("MODEL", "Pixel 6 Pro"); + propsToChangePixel6Pro.put("FINGERPRINT", "google/raven/raven:13/TQ3A.230705.001.A1/10217028:user/release-keys"); + propsToChangePixel5 = new HashMap<>(); + propsToChangePixel5.put("BRAND", "google"); + propsToChangePixel5.put("MANUFACTURER", "Google"); + propsToChangePixel5.put("DEVICE", "redfin"); + propsToChangePixel5.put("PRODUCT", "redfin"); + propsToChangePixel5.put("MODEL", "Pixel 5"); + propsToChangePixel5.put("FINGERPRINT", "google/redfin/redfin:13/TQ3A.230705.001/10216780:user/release-keys"); + propsToChangePixelXL = new HashMap<>(); + propsToChangePixelXL.put("BRAND", "google"); + propsToChangePixelXL.put("MANUFACTURER", "Google"); + propsToChangePixelXL.put("DEVICE", "marlin"); + propsToChangePixelXL.put("PRODUCT", "marlin"); + propsToChangePixelXL.put("MODEL", "Pixel XL"); + propsToChangePixelXL.put("FINGERPRINT", "google/marlin/marlin:10/QP1A.191005.007.A3/5972272:user/release-keys"); + } + + private static boolean isGoogleCameraPackage(String packageName) { + return packageName.startsWith("com.google.android.GoogleCamera") || + Arrays.asList(customGoogleCameraPackages).contains(packageName); + } + + public static void setProps(String packageName) { + propsToChangeGeneric.forEach((k, v) -> setPropValue(k, v)); + if (packageName == null || packageName.isEmpty()) { + return; + } + if (Arrays.asList(packagesToKeep).contains(packageName)) { + return; + } + if (isGoogleCameraPackage(packageName)) { + return; + } + + Map propsToChange = new HashMap<>(); + if (packageName.equals(PACKAGE_GMS) + || packageName.toLowerCase().contains("androidx.test") + || packageName.equalsIgnoreCase("com.google.android.apps.restore")) { + final String processName = Application.getProcessName(); + if (processName.toLowerCase().contains("unstable") + || processName.toLowerCase().contains("pixelmigrate") + || processName.toLowerCase().contains("instrumentation")) { + sIsGms = true; + + final boolean was = isGmsAddAccountActivityOnTop(); + final TaskStackListener taskStackListener = new TaskStackListener() { + @Override + public void onTaskStackChanged() { + final boolean is = isGmsAddAccountActivityOnTop(); + if (is ^ was) { + dlog("GmsAddAccountActivityOnTop is:" + is + " was:" + was + ", killing myself!"); + // process will restart automatically later + Process.killProcess(Process.myPid()); + } + } + }; + try { + ActivityTaskManager.getService().registerTaskStackListener(taskStackListener); + } catch (Exception e) { + Log.e(TAG, "Failed to register task stack listener!", e); + } + if (was) return; + + dlog("Spoofing build for GMS"); + // Alter build parameters to pixel 2 for avoiding hardware attestation enforcement + setBuildField("DEVICE", "walleye"); + setBuildField("FINGERPRINT", "google/walleye/walleye:8.1.0/OPM1.171019.011/4448085:user/release-keys"); + setBuildField("MODEL", "Pixel 2"); + setBuildField("PRODUCT", "walleye"); + setVersionField("DEVICE_INITIAL_SDK_INT", Build.VERSION_CODES.O); + } else if (processName.toLowerCase().contains("persistent") + || processName.toLowerCase().contains("ui") + || processName.toLowerCase().contains("learning")) { + propsToChange.putAll(propsToChangePixel6Pro); + } + return; + } + + if (packageName.startsWith("com.google.") + || packageName.startsWith("com.samsung.") + || Arrays.asList(extraPackagesToChange).contains(packageName)) { + + boolean isPixelDevice = Arrays.asList(pixelCodenames).contains(SystemProperties.get(DEVICE)); + + if (packageName.equals("com.android.vending")) { + sIsFinsky = true; + } + + if (packageName.equals("com.google.android.apps.photos")) { + propsToChange.putAll(propsToChangePixelXL); + } else if (isPixelDevice) { + return; + } else { + if (Arrays.asList(packagesToChangePixel7Pro).contains(packageName)) { + propsToChange.putAll(propsToChangePixel7Pro); + } else if (Arrays.asList(packagesToChangePixelXL).contains(packageName)) { + propsToChange.putAll(propsToChangePixelXL); + } else if (Arrays.asList(packagesToChangePixel6Pro).contains(packageName)) { + propsToChange.putAll(propsToChangePixel6Pro); + } else { + propsToChange.putAll(propsToChangePixel5); + } + } + + if (DEBUG) Log.d(TAG, "Defining props for: " + packageName); + for (Map.Entry prop : propsToChange.entrySet()) { + String key = prop.getKey(); + Object value = prop.getValue(); + if (propsToKeep.containsKey(packageName) && propsToKeep.get(packageName).contains(key)) { + if (DEBUG) Log.d(TAG, "Not defining " + key + " prop for: " + packageName); + continue; + } + if (DEBUG) Log.d(TAG, "Defining " + key + " prop for: " + packageName); + setPropValue(key, value); + } + // Set proper indexing fingerprint + if (packageName.equals("com.google.android.settings.intelligence")) { + setPropValue("FINGERPRINT", Build.VERSION.INCREMENTAL); + } + } + } + + private static void setPropValue(String key, Object value) { + try { + if (DEBUG) Log.d(TAG, "Defining prop " + key + " to " + value.toString()); + Field field = Build.class.getDeclaredField(key); + field.setAccessible(true); + field.set(null, value); + field.setAccessible(false); + } catch (NoSuchFieldException | IllegalAccessException e) { + Log.e(TAG, "Failed to set prop " + key, e); + } + } + + private static void setBuildField(String key, String value) { + try { + // Unlock + Field field = Build.class.getDeclaredField(key); + field.setAccessible(true); + + // Edit + field.set(null, value); + + // Lock + field.setAccessible(false); + } catch (NoSuchFieldException | IllegalAccessException e) { + Log.e(TAG, "Failed to spoof Build." + key, e); + } + } + + private static void setVersionField(String key, Object value) { + try { + // Unlock + if (DEBUG) Log.d(TAG, "Defining version field " + key + " to " + value.toString()); + Field field = Build.VERSION.class.getDeclaredField(key); + field.setAccessible(true); + + // Edit + field.set(null, value); + + // Lock + field.setAccessible(false); + } catch (NoSuchFieldException | IllegalAccessException e) { + Log.e(TAG, "Failed to set version field " + key, e); + } + } + + private static boolean isGmsAddAccountActivityOnTop() { + try { + final ActivityTaskManager.RootTaskInfo focusedTask = + ActivityTaskManager.getService().getFocusedRootTaskInfo(); + return focusedTask != null && focusedTask.topActivity != null + && focusedTask.topActivity.equals(GMS_ADD_ACCOUNT_ACTIVITY); + } catch (Exception e) { + Log.e(TAG, "Unable to get top activity!", e); + } + return false; + } + + public static boolean shouldBypassTaskPermission(Context context) { + // GMS doesn't have MANAGE_ACTIVITY_TASKS permission + final int callingUid = Binder.getCallingUid(); + final int gmsUid; + try { + gmsUid = context.getPackageManager().getApplicationInfo(PACKAGE_GMS, 0).uid; + dlog("shouldBypassTaskPermission: gmsUid:" + gmsUid + " callingUid:" + callingUid); + } catch (Exception e) { + Log.e(TAG, "shouldBypassTaskPermission: unable to get gms uid", e); + return false; + } + return gmsUid == callingUid; + } + + private static boolean isCallerSafetyNet() { + return sIsGms && Arrays.stream(Thread.currentThread().getStackTrace()) + .anyMatch(elem -> elem.getClassName().contains("DroidGuard")); + } + + public static void onEngineGetCertificateChain() { + // Check stack for SafetyNet or Play Integrity + if (isCallerSafetyNet() || sIsFinsky) { + Log.i(TAG, "Blocked key attestation sIsGms=" + sIsGms + " sIsFinsky=" + sIsFinsky); + throw new UnsupportedOperationException(); + } + } + + public static void dlog(String msg) { + if (DEBUG) Log.d(TAG, msg); + } + +} diff --git a/core/java/com/android/internal/util/custom/Utils.java b/core/java/com/android/internal/util/custom/Utils.java new file mode 100644 index 000000000000..056b2f4ee837 --- /dev/null +++ b/core/java/com/android/internal/util/custom/Utils.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2017-2022 crDroid Android 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.internal.util.custom; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.PowerManager; +import android.os.SystemClock; +import android.os.SystemProperties; + +import java.util.ArrayList; +import java.util.List; + +public class Utils { + + public static boolean isPackageInstalled(Context context, String packageName, boolean ignoreState) { + if (packageName != null) { + try { + PackageInfo pi = context.getPackageManager().getPackageInfo(packageName, 0); + if (!pi.applicationInfo.enabled && !ignoreState) { + return false; + } + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + return true; + } + + public static boolean isPackageInstalled(Context context, String packageName) { + return isPackageInstalled(context, packageName, true); + } + + public static boolean isPackageEnabled(Context context, String packageName) { + try { + PackageInfo pi = context.getPackageManager().getPackageInfo(packageName, 0); + return pi.applicationInfo.enabled; + } catch (PackageManager.NameNotFoundException notFound) { + return false; + } + } + + public static List launchablePackages(Context context) { + List list = new ArrayList<>(); + + Intent filter = new Intent(Intent.ACTION_MAIN, null); + filter.addCategory(Intent.CATEGORY_LAUNCHER); + + List apps = context.getPackageManager().queryIntentActivities(filter, + PackageManager.GET_META_DATA); + + int numPackages = apps.size(); + for (int i = 0; i < numPackages; i++) { + ResolveInfo app = apps.get(i); + list.add(app.activityInfo.packageName); + } + + return list; + } + + public static void switchScreenOff(Context ctx) { + PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); + if (pm!= null) { + pm.goToSleep(SystemClock.uptimeMillis()); + } + } + + public static boolean deviceHasFlashlight(Context ctx) { + return ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH); + } + + public static boolean hasNavbarByDefault(Context context) { + boolean needsNav = context.getResources().getBoolean( + com.android.internal.R.bool.config_showNavigationBar); + String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); + if ("1".equals(navBarOverride)) { + needsNav = false; + } else if ("0".equals(navBarOverride)) { + needsNav = true; + } + return needsNav; + } +} diff --git a/core/java/com/android/internal/util/custom/cutout/CutoutFullscreenController.java b/core/java/com/android/internal/util/custom/cutout/CutoutFullscreenController.java new file mode 100644 index 000000000000..c30b38eef4b7 --- /dev/null +++ b/core/java/com/android/internal/util/custom/cutout/CutoutFullscreenController.java @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2018 The LineageOS project + * Copyright (C) 2019 The PixelExperience 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.internal.util.custom.cutout; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.res.Resources; +import android.database.ContentObserver; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.text.TextUtils; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import android.provider.Settings; + +public class CutoutFullscreenController { + private Set mApps = new HashSet<>(); + private Context mContext; + + private final boolean isAvailable; + + public CutoutFullscreenController(Context context) { + mContext = context; + final Resources resources = mContext.getResources(); + + final String displayCutout = resources.getString(com.android.internal.R.string.config_mainBuiltInDisplayCutout); + isAvailable = !TextUtils.isEmpty(displayCutout); + + if (!isAvailable) { + return; + } + + SettingsObserver observer = new SettingsObserver( + new Handler(Looper.getMainLooper())); + observer.observe(); + } + + public boolean isSupported() { + return isAvailable; + } + + public boolean shouldForceCutoutFullscreen(String packageName) { + return isSupported() && mApps.contains(packageName); + } + + public Set getApps() { + return mApps; + } + + public void addApp(String packageName) { + mApps.add(packageName); + Settings.System.putString(mContext.getContentResolver(), + Settings.System.FORCE_FULLSCREEN_CUTOUT_APPS, String.join(",", mApps)); + } + + public void removeApp(String packageName) { + mApps.remove(packageName); + Settings.System.putString(mContext.getContentResolver(), + Settings.System.FORCE_FULLSCREEN_CUTOUT_APPS, String.join(",", mApps)); + } + + public void setApps(Set apps) { + mApps = apps; + } + + class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + void observe() { + ContentResolver resolver = mContext.getContentResolver(); + + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.FORCE_FULLSCREEN_CUTOUT_APPS), false, this, + UserHandle.USER_ALL); + + update(); + } + + @Override + public void onChange(boolean selfChange) { + update(); + } + + public void update() { + ContentResolver resolver = mContext.getContentResolver(); + + String apps = Settings.System.getStringForUser(resolver, + Settings.System.FORCE_FULLSCREEN_CUTOUT_APPS, + UserHandle.USER_CURRENT); + if (apps != null) { + setApps(new HashSet<>(Arrays.asList(apps.split(",")))); + } else { + setApps(new HashSet<>()); + } + } + } +} diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index bc4c9c314f5b..8942916d024c 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -80,6 +80,11 @@ public class LockPatternUtils { */ public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled"; + /** + * The key to store PIN/Password length for quick unlock. + **/ + public static final String KEY_PIN_PASSWORD_LENGTH = "pin_password_length"; + /** * The interval of the countdown for showing progress of the lockout. */ @@ -1883,4 +1888,23 @@ public void removeCachedUnifiedChallenge(int userId) { re.rethrowFromSystemServer(); } } + + public int getPinPasswordLength(int userId) { + int mPinPasswordLength = -1; + try { + mPinPasswordLength = (int) getLockSettings().getLong(KEY_PIN_PASSWORD_LENGTH, -1, + userId); + } catch (Exception e) { + Log.d("getPinPasswordLength", "getLong error: " + e.getMessage()); + } + return mPinPasswordLength; + } + + public void setPinPasswordLength(int length, int userId) { + try { + getLockSettings().setLong(KEY_PIN_PASSWORD_LENGTH, (long) length, userId); + } catch (Exception e) { + Log.d("savePinPasswordLength", "saveLong error: " + e.getMessage()); + } + } } diff --git a/core/java/com/android/server/LocalServices.java b/core/java/com/android/server/LocalServices.java index 9c632ea725a9..ca94bb08afc0 100644 --- a/core/java/com/android/server/LocalServices.java +++ b/core/java/com/android/server/LocalServices.java @@ -18,7 +18,7 @@ import com.android.internal.annotations.VisibleForTesting; -import android.util.ArrayMap; +import java.util.HashMap; /** * This class is used in a similar way as ServiceManager, except the services registered here @@ -32,8 +32,8 @@ public final class LocalServices { private LocalServices() {} - private static final ArrayMap, Object> sLocalServiceObjects = - new ArrayMap, Object>(); + private static final HashMap, Object> sLocalServiceObjects = + new HashMap, Object>(); /** * Returns a local service instance that implements the specified interface. diff --git a/core/jni/Android.bp b/core/jni/Android.bp index aa661713b1fe..543123338379 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -50,6 +50,7 @@ cc_library_shared { "android_util_XmlBlock.cpp", "android_util_jar_StrictJarFile.cpp", "com_android_internal_util_VirtualRefBasePtr.cpp", + "com_android_internal_app_ActivityTrigger.cpp", ":deviceproductinfoconstants_aidl", ], @@ -406,9 +407,8 @@ cc_library_shared { }, }, - // Workaround Clang LTO crash. lto: { - never: true, + thin: true, }, } diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index eba6cca76389..351ac91d3fd1 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -211,6 +211,7 @@ extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env); extern int register_com_android_internal_security_VerityUtils(JNIEnv* env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); extern int register_android_window_WindowInfosListener(JNIEnv* env); +extern int register_com_android_internal_app_ActivityTrigger(JNIEnv *env); // Namespace for Android Runtime flags applied during boot time. static const char* RUNTIME_NATIVE_BOOT_NAMESPACE = "runtime_native_boot"; @@ -1651,6 +1652,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_animation_PropertyValuesHolder), REG_JNI(register_android_security_Scrypt), + REG_JNI(register_com_android_internal_app_ActivityTrigger), REG_JNI(register_com_android_internal_content_F2fsUtils), REG_JNI(register_com_android_internal_content_NativeLibraryHelper), REG_JNI(register_com_android_internal_os_FuseAppLoop), diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index d1602aecde85..3c19e5b764b7 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -470,6 +470,56 @@ void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualM } } +static void android_hardware_Camera_setLongshot(JNIEnv *env, jobject thiz, jboolean enable) +{ + ALOGV("setLongshot"); + JNICameraContext* context; + status_t rc; + sp camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if ( enable ) { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_ON, 0, 0); + } else { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_OFF, 0, 0); + } + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "enabling longshot mode failed"); + } +} + +static void android_hardware_Camera_sendHistogramData(JNIEnv *env, jobject thiz) + { + ALOGV("sendHistogramData" ); + JNICameraContext* context; + status_t rc; + sp camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_SEND_DATA, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "send histogram data failed"); + } + } + static void android_hardware_Camera_setHistogramMode(JNIEnv *env, jobject thiz, jboolean mode) + { + ALOGV("setHistogramMode: mode:%d", (int)mode); + JNICameraContext* context; + status_t rc; + sp camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if(mode == true) + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_ON, 0, 0); + else + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_OFF, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "set histogram mode failed"); + } + } void JNICameraContext::addCallbackBuffer( JNIEnv *env, jbyteArray cbb, int msgType) { @@ -784,7 +834,25 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t context->setCallbackMode(env, installed, manualBuffer); } -static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, jint msgType) { +static void android_hardware_Camera_setMetadataCb(JNIEnv *env, jobject thiz, jboolean mode) +{ + ALOGV("setMetadataCb: mode:%d", (int)mode); + JNICameraContext* context; + status_t rc; + sp camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if(mode == true) + rc = camera->sendCommand(CAMERA_CMD_METADATA_ON, 0, 0); + else + rc = camera->sendCommand(CAMERA_CMD_METADATA_OFF, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "set metadata mode failed"); + } +} + +static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, int msgType) { ALOGV("addCallbackBuffer: 0x%x", msgType); JNICameraContext* context = reinterpret_cast(env->GetLongField(thiz, fields.context)); @@ -1072,6 +1140,10 @@ static const JNINativeMethod camMethods[] = { {"native_autoFocus", "()V", (void *)android_hardware_Camera_autoFocus}, {"native_cancelAutoFocus", "()V", (void *)android_hardware_Camera_cancelAutoFocus}, {"native_takePicture", "(I)V", (void *)android_hardware_Camera_takePicture}, + {"native_setHistogramMode", "(Z)V", (void *)android_hardware_Camera_setHistogramMode}, + {"native_setMetadataCb", "(Z)V", (void *)android_hardware_Camera_setMetadataCb}, + {"native_sendHistogramData", "()V", (void *)android_hardware_Camera_sendHistogramData}, + {"native_setLongshot", "(Z)V", (void *)android_hardware_Camera_setLongshot}, {"native_setParameters", "(Ljava/lang/String;)V", (void *)android_hardware_Camera_setParameters}, {"native_getParameters", "()Ljava/lang/String;", diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 9adeb92796bf..073eddf8cba2 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,9 @@ #include "android_util_Binder.h" #include "core_jni_helpers.h" +static jclass gAppVolumeClass; +static jmethodID gAppVolumeCstor; + // ---------------------------------------------------------------------------- using namespace android; @@ -844,6 +848,88 @@ android_media_AudioSystem_getMasterBalance(JNIEnv *env, jobject thiz) return balance; } +static jint +android_media_AudioSystem_setAppVolume(JNIEnv *env, jobject thiz, jstring packageName, jfloat value) +{ + const jchar* c_packageName = env->GetStringCritical(packageName, 0); + String8 package8 = String8(reinterpret_cast(c_packageName), env->GetStringLength(packageName)); + env->ReleaseStringCritical(packageName, c_packageName); + return (jint) check_AudioSystem_Command(AudioSystem::setAppVolume(package8, value)); +} + +static jint +android_media_AudioSystem_setAppMute(JNIEnv *env, jobject thiz, jstring packageName, jboolean mute) +{ + const jchar* c_packageName = env->GetStringCritical(packageName, 0); + String8 package8 = String8(reinterpret_cast(c_packageName), env->GetStringLength(packageName)); + env->ReleaseStringCritical(packageName, c_packageName); + return (jint) check_AudioSystem_Command(AudioSystem::setAppMute(package8, mute)); +} + +jint convertAppVolumeFromNative(JNIEnv *env, jobject *jAppVolume, const media::AppVolume *AppVolume) +{ + jint jStatus = (jint)AUDIO_JAVA_SUCCESS; + jstring jPackageName; + jfloat jVolume; + jboolean jMute; + jboolean jActive; + + if (AppVolume == NULL || jAppVolume == NULL) { + jStatus = (jint)AUDIO_JAVA_ERROR; + goto exit; + } + + jPackageName = env->NewStringUTF(AppVolume->packageName); + jVolume = AppVolume->volume; + jMute = AppVolume->muted; + jActive = AppVolume->active; + + *jAppVolume = env->NewObject(gAppVolumeClass, gAppVolumeCstor, + jPackageName, jMute, jVolume, jActive); + + env->DeleteLocalRef(jPackageName); +exit: + return jStatus; +} + +static jint +android_media_AudioSystem_listAppVolumes(JNIEnv *env, jobject clazz, jobject jVolumes) +{ + ALOGV("listAppVolumes"); + + if (jVolumes == NULL) { + ALOGE("listAppVolumes NULL AppVolume ArrayList"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + if (!env->IsInstanceOf(jVolumes, gArrayListClass)) { + ALOGE("listAppVolumes not an arraylist"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + + std::vector volumes; + + jint jStatus = (jint)AUDIO_JAVA_SUCCESS; + status_t status = AudioSystem::listAppVolumes(&volumes); + + if (status != NO_ERROR) { + ALOGE("AudioSystem::listAppVolumes error %d", status); + jStatus = nativeToJavaStatus(status); + return jStatus; + } + + for (size_t i = 0; i < volumes.size(); i++) { + jobject jAppVolume; + jStatus = convertAppVolumeFromNative(env, &jAppVolume, &volumes[i]); + if (jStatus != AUDIO_JAVA_SUCCESS) { + return jStatus; + } + env->CallBooleanMethod(jVolumes, gArrayListMethods.add, jAppVolume); + env->DeleteLocalRef(jAppVolume); + } + + return jStatus; +} + static jint android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz) { @@ -3105,7 +3191,13 @@ static const JNINativeMethod gMethods[] = (void *)android_media_AudioSystem_getDirectPlaybackSupport}, {"getDirectProfilesForAttributes", "(Landroid/media/AudioAttributes;Ljava/util/ArrayList;)I", - (void *)android_media_AudioSystem_getDirectProfilesForAttributes}}; + (void *)android_media_AudioSystem_getDirectProfilesForAttributes}, + {"setAppVolume", "(Ljava/lang/String;F)I", + (void *)android_media_AudioSystem_setAppVolume}, + {"setAppMute", "(Ljava/lang/String;Z)I", + (void *)android_media_AudioSystem_setAppMute}, + {"listAppVolumes", "(Ljava/util/ArrayList;)I", + (void *)android_media_AudioSystem_listAppVolumes}}; static const JNINativeMethod gEventHandlerMethods[] = { {"native_setup", @@ -3344,6 +3436,11 @@ int register_android_media_AudioSystem(JNIEnv *env) gVibratorMethods.getMaxAmplitude = GetMethodIDOrDie(env, vibratorClass, "getHapticChannelMaximumAmplitude", "()F"); + jclass AppVolumeClass = FindClassOrDie(env, "android/media/AppVolume"); + gAppVolumeClass = MakeGlobalRefOrDie(env, AppVolumeClass); + gAppVolumeCstor = GetMethodIDOrDie(env, AppVolumeClass, "", + "(Ljava/lang/String;ZFZ)V"); + AudioSystem::addErrorCallback(android_media_AudioSystem_error_callback); RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp index 0a5e78617568..2e9aa3405dac 100644 --- a/core/jni/android_util_EventLog.cpp +++ b/core/jni/android_util_EventLog.cpp @@ -68,16 +68,16 @@ static void android_util_EventLog_readEventsOnWrapping(JNIEnv* env, jobject claz */ static const JNINativeMethod gRegisterMethods[] = { /* name, signature, funcPtr */ - { "writeEvent", "(II)I", (void*) ELog::writeEventInteger }, - { "writeEvent", "(IJ)I", (void*) ELog::writeEventLong }, - { "writeEvent", "(IF)I", (void*) ELog::writeEventFloat }, - { "writeEvent", "(ILjava/lang/String;)I", (void*) ELog::writeEventString }, - { "writeEvent", "(I[Ljava/lang/Object;)I", (void*) ELog::writeEventArray }, - { "readEvents", + { "nativeWriteEvent", "(II)I", (void*) ELog::writeEventInteger }, + { "nativeWriteEvent", "(IJ)I", (void*) ELog::writeEventLong }, + { "nativeWriteEvent", "(IF)I", (void*) ELog::writeEventFloat }, + { "nativeWriteEvent", "(ILjava/lang/String;)I", (void*) ELog::writeEventString }, + { "nativeWriteEvent", "(I[Ljava/lang/Object;)I", (void*) ELog::writeEventArray }, + { "nativeReadEvents", "([ILjava/util/Collection;)V", (void*) android_util_EventLog_readEvents }, - { "readEventsOnWrapping", + { "nativeReadEventsOnWrapping", "([IJLjava/util/Collection;)V", (void*) android_util_EventLog_readEventsOnWrapping }, diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index b9d5ee4b3015..4f19cdade122 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -279,6 +279,81 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin signalExceptionForGroupError(env, errno ? errno : EPERM, pid); } +void android_os_Process_setCgroupProcsProcessGroup(JNIEnv* env, jobject clazz, int uid, int pid, jint grp, jboolean dex2oat_only) +{ + int fd; + char pathV1[255], pathV2[255]; + static bool isCgroupV2 = false; + if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) { + signalExceptionForGroupError(env, EINVAL, pid); + return; + } + + //set process group for current process + android_os_Process_setProcessGroup(env, clazz, pid, grp); + + //find processes in the same cgroup.procs of current uid and pid + snprintf(pathV1, sizeof(pathV1), "/acct/uid_%d/pid_%d/cgroup.procs", uid, pid); + snprintf(pathV2, sizeof(pathV2), "/sys/fs/cgroup/uid_%d/pid_%d/cgroup.procs", uid, pid); + if (isCgroupV2) { + // read from V2 only + fd = open(pathV2, O_RDONLY); + } else { + // first try V1 + fd = open(pathV1, O_RDONLY); + if (fd < 0) { + fd = open(pathV2, O_RDONLY); + if (fd >= 0) { + isCgroupV2 = true; + } + } + } + if (fd >= 0) { + char buffer[256]; + char ch; + int numRead; + size_t len=0; + for (;;) { + numRead=read(fd, &ch, 1); + if (numRead <= 0) + break; + if (ch != '\n') { + buffer[len++] = ch; + } else { + int temp_pid = atoi(buffer); + len=0; + if (temp_pid == pid) + continue; + if (dex2oat_only) { + // check if cmdline of temp_pid is dex2oat + char cmdline[64]; + snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", temp_pid); + int cmdline_fd = open(cmdline, O_RDONLY); + if (cmdline_fd >= 0) { + size_t read_size = read(cmdline_fd, buffer, 255); + close(cmdline_fd); + buffer[read_size]='\0'; + const char *dex2oat_name1 = "dex2oat"; //for plugins compiler + const char *dex2oat_name2 = "/system/bin/dex2oat"; //for installer + const char *dex2oat_name3 = "/apex/com.android.runtime/bin/dex2oat"; //for installer + if (strncmp(buffer, dex2oat_name1, strlen(dex2oat_name1)) != 0 + && strncmp(buffer, dex2oat_name2, strlen(dex2oat_name2)) != 0 + && strncmp(buffer, dex2oat_name3, strlen(dex2oat_name3)) != 0) { + continue; + } + } else { + //ALOGE("read %s failed", cmdline); + continue; + } + } + //set cgroup of temp_pid follow pid + android_os_Process_setProcessGroup(env, clazz, temp_pid, grp); + } + } + close(fd); + } +} + void android_os_Process_setProcessFrozen( JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze) { @@ -356,8 +431,21 @@ static void get_cpuset_cores_for_policy(SchedPolicy policy, cpu_set_t *cpu_set) } break; case SP_FOREGROUND: + if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) { + return; + } + break; case SP_AUDIO_APP: case SP_AUDIO_SYS: + if (!CgroupGetAttributePath("AudioAppCapacityCPUs", &filename)) { + return; + } + if (access(filename.c_str(), F_OK) != 0) { + if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) { + return; + } + } + break; case SP_RT_APP: if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) { return; @@ -1263,6 +1351,7 @@ static const JNINativeMethod methods[] = { {"getThreadScheduler", "(I)I", (void*)android_os_Process_getThreadScheduler}, {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup}, {"setThreadGroupAndCpuset", "(II)V", (void*)android_os_Process_setThreadGroupAndCpuset}, + {"setCgroupProcsProcessGroup", "(IIIZ)V", (void*)android_os_Process_setCgroupProcsProcessGroup}, {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup}, {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup}, {"createProcessGroup", "(II)I", (void*)android_os_Process_createProcessGroup}, diff --git a/core/jni/com_android_internal_app_ActivityTrigger.cpp b/core/jni/com_android_internal_app_ActivityTrigger.cpp new file mode 100644 index 000000000000..9d22f69d91ea --- /dev/null +++ b/core/jni/com_android_internal_app_ActivityTrigger.cpp @@ -0,0 +1,256 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_TAG "ActTriggerJNI" + +#include "jni.h" +#include +#include + +#include +#include +#include + +#include +#include + +namespace android +{ + +// ---------------------------------------------------------------------------- +/* + * Stuct containing handle to dynamically loaded lib as well as function + * pointers to key interfaces. + */ +typedef struct dlLibHandler { + void *dlhandle; + void (*startActivity)(const char *, int *); + void (*startApp)(const char *, int *); + void (*resumeActivity)(const char *); + void (*pauseActivity)(const char *); + void (*stopActivity)(const char *); + void (*init)(void); + void (*deinit)(void); + void (*miscActivity)(int, const char *, int, int, float *); + const char *dlname; +}dlLibHandler; + +/* + * Init for activity trigger library + */ +static dlLibHandler mDlLibHandler = { + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "libqti-at.so" +}; + +// ---------------------------------------------------------------------------- + +static void +com_android_internal_app_ActivityTrigger_native_at_init() +{ + bool errored = false; + + mDlLibHandler.dlhandle = dlopen(mDlLibHandler.dlname, RTLD_NOW | RTLD_LOCAL); + if (mDlLibHandler.dlhandle == NULL) { + return; + } + + *(void **) (&mDlLibHandler.startActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_start"); + if (mDlLibHandler.startActivity == NULL) { + errored = true; + } + + *(void **) (&mDlLibHandler.startApp) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_qspm_start"); + + if (!errored) { + *(void **) (&mDlLibHandler.resumeActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_resume"); + if (mDlLibHandler.resumeActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.pauseActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_pause"); + if (mDlLibHandler.pauseActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.stopActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_stop"); + if (mDlLibHandler.stopActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.init) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_init"); + if (mDlLibHandler.init == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.miscActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_misc"); + if (mDlLibHandler.miscActivity == NULL) { + errored = true; + } + } + if (errored) { + mDlLibHandler.startActivity = NULL; + mDlLibHandler.startApp = NULL; + mDlLibHandler.resumeActivity = NULL; + mDlLibHandler.pauseActivity = NULL; + mDlLibHandler.stopActivity = NULL; + mDlLibHandler.miscActivity = NULL; + if (mDlLibHandler.dlhandle) { + dlclose(mDlLibHandler.dlhandle); + mDlLibHandler.dlhandle = NULL; + } + } else { + (*mDlLibHandler.init)(); + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_deinit(JNIEnv *env, jobject clazz) +{ + if (mDlLibHandler.dlhandle) { + mDlLibHandler.startActivity = NULL; + mDlLibHandler.startApp = NULL; + mDlLibHandler.resumeActivity = NULL; + mDlLibHandler.pauseActivity = NULL; + mDlLibHandler.stopActivity = NULL; + mDlLibHandler.miscActivity = NULL; + + *(void **) (&mDlLibHandler.deinit) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_deinit"); + if (mDlLibHandler.deinit) { + (*mDlLibHandler.deinit)(); + } + + dlclose(mDlLibHandler.dlhandle); + mDlLibHandler.dlhandle = NULL; + } +} + +static jint +com_android_internal_app_ActivityTrigger_native_at_startActivity(JNIEnv *env, jobject clazz, jstring activity, jint flags) +{ + int activiyFlags = flags; + if(mDlLibHandler.startActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.startActivity)(actStr, &activiyFlags); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return activiyFlags; +} + +static jint +com_android_internal_app_ActivityTrigger_native_at_startApp(JNIEnv *env, jobject clazz, jstring activity, jint flags) +{ + int activiyFlags = flags; + if(mDlLibHandler.startApp && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.startApp)(actStr, &activiyFlags); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return activiyFlags; +} + +static void +com_android_internal_app_ActivityTrigger_native_at_resumeActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.resumeActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.resumeActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_pauseActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.pauseActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (NULL != actStr) { + (*mDlLibHandler.pauseActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_stopActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.stopActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (NULL != actStr) { + (*mDlLibHandler.stopActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static jfloat +com_android_internal_app_ActivityTrigger_native_at_miscActivity(JNIEnv *env, jobject clazz, jint func, jstring activity, jint type, jint flag) +{ + float scaleValue = -1.0f; + if (mDlLibHandler.miscActivity && activity && func) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.miscActivity)(func, actStr, type, flag, &scaleValue); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return scaleValue; +} + +// ---------------------------------------------------------------------------- + +static JNINativeMethod gMethods[] = { + {"native_at_startActivity", "(Ljava/lang/String;I)I", (void *)com_android_internal_app_ActivityTrigger_native_at_startActivity}, + {"native_at_startApp", "(Ljava/lang/String;I)I", (void *)com_android_internal_app_ActivityTrigger_native_at_startApp}, + {"native_at_resumeActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_resumeActivity}, + {"native_at_pauseActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_pauseActivity}, + {"native_at_stopActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_stopActivity}, + {"native_at_deinit", "()V", (void *)com_android_internal_app_ActivityTrigger_native_at_deinit}, + {"native_at_miscActivity", "(ILjava/lang/String;II)F", (void *)com_android_internal_app_ActivityTrigger_native_at_miscActivity}, +}; + +int register_com_android_internal_app_ActivityTrigger(JNIEnv *env) +{ + com_android_internal_app_ActivityTrigger_native_at_init(); + + return AndroidRuntime::registerNativeMethods(env, + "com/android/internal/app/ActivityTrigger", gMethods, NELEM(gMethods)); +} + +} // namespace android diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index c8b85c314aca..5d9fadab554e 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -339,6 +339,7 @@ enum MountExternalKind { // Must match values in com.android.internal.os.Zygote. enum RuntimeFlags : uint32_t { DEBUG_ENABLE_JDWP = 1, + PROFILE_SYSTEM_SERVER = 1 << 14, PROFILE_FROM_SHELL = 1 << 15, MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20), MEMORY_TAG_LEVEL_TBI = 1 << 19, @@ -1786,10 +1787,11 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, // since the directory is owned by root. if (!is_system_server && getuid() == 0) { const int rc = createProcessGroup(uid, getpid()); - if (rc == -EROFS) { - ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?"); - } else if (rc != 0) { - ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc)); + if (rc != 0) { + fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing " + "CONFIG_CGROUP_CPUACCT?") + : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid, + /* pid= */ 0, strerror(-rc))); } } @@ -1804,9 +1806,11 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, instruction_set.value().c_str()); } - if (is_system_server) { + if (is_system_server && !(runtime_flags & RuntimeFlags::PROFILE_SYSTEM_SERVER)) { // Prefetch the classloader for the system server. This is done early to // allow a tie-down of the proper system server selinux domain. + // We don't prefetch when the system server is being profiled to avoid + // loading AOT code. env->CallStaticObjectMethod(gZygoteInitClass, gGetOrCreateSystemServerClassLoader); if (env->ExceptionCheck()) { // Be robust here. The Java code will attempt to create the classloader diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index bbc3a7369423..ade2a2c59026 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -827,6 +827,10 @@ + + + + @@ -1241,7 +1245,7 @@ @@ -3577,6 +3581,21 @@ android:description="@string/permdesc_getPackageSize" android:protectionLevel="normal" /> + + + + + + @@ -6568,6 +6587,11 @@ + + + diff --git a/core/res/res/drawable-hdpi/stat_notify_missed_call.png b/core/res/res/drawable-hdpi/stat_notify_missed_call.png deleted file mode 100644 index f205471bc5f1..000000000000 Binary files a/core/res/res/drawable-hdpi/stat_notify_missed_call.png and /dev/null differ diff --git a/core/res/res/drawable-ldpi/stat_notify_missed_call.png b/core/res/res/drawable-ldpi/stat_notify_missed_call.png deleted file mode 100644 index 4c01206df673..000000000000 Binary files a/core/res/res/drawable-ldpi/stat_notify_missed_call.png and /dev/null differ diff --git a/core/res/res/drawable-mdpi/stat_notify_missed_call.png b/core/res/res/drawable-mdpi/stat_notify_missed_call.png deleted file mode 100644 index f2ff56e21ba7..000000000000 Binary files a/core/res/res/drawable-mdpi/stat_notify_missed_call.png and /dev/null differ diff --git a/core/res/res/drawable-xhdpi/stat_notify_missed_call.png b/core/res/res/drawable-xhdpi/stat_notify_missed_call.png deleted file mode 100644 index 8719eff5ae1a..000000000000 Binary files a/core/res/res/drawable-xhdpi/stat_notify_missed_call.png and /dev/null differ diff --git a/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png b/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png deleted file mode 100644 index 904df3baa20d..000000000000 Binary files a/core/res/res/drawable-xxhdpi/stat_notify_missed_call.png and /dev/null differ diff --git a/core/res/res/drawable/ic_account_circle.xml b/core/res/res/drawable/ic_account_circle.xml index 71691add7322..b83598c51fb7 100644 --- a/core/res/res/drawable/ic_account_circle.xml +++ b/core/res/res/drawable/ic_account_circle.xml @@ -20,8 +20,5 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24"> - + android:pathData="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M7.07,18.28C7.5,17.38 10.12,16.5 12,16.5C13.88,16.5 16.5,17.38 16.93,18.28C15.57,19.36 13.86,20 12,20C10.14,20 8.43,19.36 7.07,18.28M18.36,16.83C16.93,15.09 13.46,14.5 12,14.5C10.54,14.5 7.07,15.09 5.64,16.83C4.62,15.5 4,13.82 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,13.82 19.38,15.5 18.36,16.83M12,6C10.06,6 8.5,7.56 8.5,9.5C8.5,11.44 10.06,13 12,13C13.94,13 15.5,11.44 15.5,9.5C15.5,7.56 13.94,6 12,6M12,11A1.5,1.5 0 0,1 10.5,9.5A1.5,1.5 0 0,1 12,8A1.5,1.5 0 0,1 13.5,9.5A1.5,1.5 0 0,1 12,11Z" /> diff --git a/core/res/res/drawable/ic_alarm_on.xml b/core/res/res/drawable/ic_alarm_on.xml new file mode 100644 index 000000000000..bdcf7547c664 --- /dev/null +++ b/core/res/res/drawable/ic_alarm_on.xml @@ -0,0 +1,10 @@ + + + diff --git a/core/res/res/drawable/ic_audio_media.xml b/core/res/res/drawable/ic_audio_media.xml index 4ef5340138b1..fd3c0deb75b6 100644 --- a/core/res/res/drawable/ic_audio_media.xml +++ b/core/res/res/drawable/ic_audio_media.xml @@ -22,7 +22,7 @@ + android:pathData="M12,3l0.01,10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55C7.79,13 6,14.79 6,17c0,2.21 1.79,4 4.01,4S14,19.21 14,17V7h4V3H12zM10.01,19c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2C12.01,18.1 11.11,19 10.01,19z"/> diff --git a/core/res/res/drawable/ic_audio_media_mute.xml b/core/res/res/drawable/ic_audio_media_mute.xml index 2be6dc42af4d..210aee81451c 100644 --- a/core/res/res/drawable/ic_audio_media_mute.xml +++ b/core/res/res/drawable/ic_audio_media_mute.xml @@ -22,10 +22,10 @@ + android:pathData="M21.19,21.19L14,14l-2,-2l-9.2,-9.2L1.39,4.22l8.79,8.79c-0.06,0 -0.12,-0.01 -0.18,-0.01C7.79,13 6,14.79 6,17c0,2.21 1.79,4 4.01,4S14,19.21 14,17v-0.17l5.78,5.78L21.19,21.19zM10.01,19c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2C12.01,18.1 11.11,19 10.01,19z"/> + android:pathData="M14,11.17l0,-4.17l4,0l0,-4l-6,0l0,6.17z"/> diff --git a/core/res/res/drawable/ic_audio_ring_notif.xml b/core/res/res/drawable/ic_audio_ring_notif.xml index 54c4074771c2..47a08966aec2 100644 --- a/core/res/res/drawable/ic_audio_ring_notif.xml +++ b/core/res/res/drawable/ic_audio_ring_notif.xml @@ -22,5 +22,8 @@ Copyright (C) 2014 The Android Open Source Project + android:pathData="M18,17v-6c0,-3.07 -1.63,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C7.64,5.36 6,7.92 6,11v6H4v2h10h0.38H20v-2H18zM16,17H8v-6c0,-2.48 1.51,-4.5 4,-4.5s4,2.02 4,4.5V17z"/> + diff --git a/core/res/res/drawable/ic_audio_ring_notif_mute.xml b/core/res/res/drawable/ic_audio_ring_notif_mute.xml index b5915207b7f1..c838fe245d11 100644 --- a/core/res/res/drawable/ic_audio_ring_notif_mute.xml +++ b/core/res/res/drawable/ic_audio_ring_notif_mute.xml @@ -22,5 +22,11 @@ Copyright (C) 2014 The Android Open Source Project + android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z"/> + + diff --git a/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml b/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml index b3a285924044..52b5b67be6ec 100644 --- a/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml +++ b/core/res/res/drawable/ic_audio_ring_notif_vibrate.xml @@ -1,17 +1,18 @@ + + android:pathData="M17.8,12c0,2.51,0,5,0,7.53a1.76,1.76,0,0,1-1.29,1.68,2.24,2.24,0,0,1-0.57 0.08 H8.09a2,2,0,0,1-1-0.2,1.73,1.73,0,0,1-0.94-1.45c0-0.12,0-0.24,0-0.35V4.71a3,3,0,0,1,0-0.6A1.78,1.78,0,0,1,7.86,2.74l0.3,0h7.5l0.36,0a1.59,1.59,0,0,1,0.8 0.18 A1.66,1.66,0,0,1,17.74,4a1.86,1.86,0,0,1,0.06 0.34 c0,0.12,0,0.24,0,0.37V12ZM15.9,4.67H8.1l0,0V19.25c0,0.05,0,0.11,0,0.16a0,0,0,0,0,0,0v0H15.9Z" /> + + diff --git a/core/res/res/drawable/ic_audio_vol.xml b/core/res/res/drawable/ic_audio_vol.xml index fc216e5b699a..f66c316b897e 100644 --- a/core/res/res/drawable/ic_audio_vol.xml +++ b/core/res/res/drawable/ic_audio_vol.xml @@ -16,10 +16,10 @@ Copyright (C) 2014 The Android Open Source Project + android:pathData="M3 9v6h4l5 5V4L7 9H3zm7-0.17v6.34L7.83 13H5v-2h2.83L10 8.83zM16.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-0.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89 0.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-0.91 7-4.49 7-8.77 0-4.28-2.99-7.86-7-8.77z" /> diff --git a/core/res/res/drawable/ic_audio_vol_mute.xml b/core/res/res/drawable/ic_audio_vol_mute.xml index 7cf604c614be..d102676fe126 100644 --- a/core/res/res/drawable/ic_audio_vol_mute.xml +++ b/core/res/res/drawable/ic_audio_vol_mute.xml @@ -16,10 +16,10 @@ Copyright (C) 2014 The Android Open Source Project + android:pathData="M4.34 2.93L2.93 4.34 7.29 8.7 7 9H3v6h4l5 5v-6.59l4.18 4.18c-0.65 0.49 -1.38 0.88 -2.18 1.11v2.06c1.34-0.3 2.57-0.92 3.61-1.75l2.05 2.05 1.41-1.41L4.34 2.93zM10 15.17L7.83 13H5v-2h2.83l0.88-0.88L10 11.41v3.76zM19 12c0 0.82-0.15 1.61-0.41 2.34l1.53 1.53c0.56-1.17 0.88 -2.48 0.88 -3.87 0-4.28-2.99-7.86-7-8.77v2.06c2.89 0.86 5 3.54 5 6.71zm-7-8l-1.88 1.88L12 7.76zm4.5 8c0-1.77-1.02-3.29-2.5-4.03v1.79l2.48 2.48c0.01-0.08 0.02 -0.16 0.02 -0.24z" /> diff --git a/core/res/res/drawable/ic_battery.xml b/core/res/res/drawable/ic_battery.xml index bd40f4df505e..318d125ed256 100644 --- a/core/res/res/drawable/ic_battery.xml +++ b/core/res/res/drawable/ic_battery.xml @@ -21,5 +21,5 @@ android:tint="?android:attr/colorControlNormal"> + android:pathData="M16,20H8V6H16M16.67,4H15V2H9V4H7.33A1.33,1.33 0 0,0 6,5.33V20.67C6,21.4 6.6,22 7.33,22H16.67A1.33,1.33 0 0,0 18,20.67V5.33C18,4.6 17.4,4 16.67,4Z" /> diff --git a/core/res/res/drawable/ic_bt_headphones_a2dp.xml b/core/res/res/drawable/ic_bt_headphones_a2dp.xml index 32f39a39754f..aa53b61387fb 100644 --- a/core/res/res/drawable/ic_bt_headphones_a2dp.xml +++ b/core/res/res/drawable/ic_bt_headphones_a2dp.xml @@ -21,6 +21,5 @@ android:tint="?android:attr/colorControlNormal"> + android:pathData="M19,15v3c0,0.55 -0.45,1 -1,1h-1v-4h2M7,15v4H6c-0.55,0 -1,-0.45 -1,-1v-3h2m5,-13c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h3c1.66,0 3,-1.34 3,-3v-7c0,-4.97 -4.03,-9 -9,-9z" /> \ No newline at end of file diff --git a/core/res/res/drawable/ic_bt_headset_hfp.xml b/core/res/res/drawable/ic_bt_headset_hfp.xml index e43fe39409af..f2066ed7c6cd 100644 --- a/core/res/res/drawable/ic_bt_headset_hfp.xml +++ b/core/res/res/drawable/ic_bt_headset_hfp.xml @@ -21,7 +21,5 @@ android:tint="?android:attr/colorControlNormal"> + android:pathData="M12,1c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-1.71C5,6.45 7.96,3.11 11.79,3C15.76,2.89 19,6.06 19,10v2h-4v8h4v1h-6v2h6c1.1,0 2,-0.9 2,-2V10C21,5.03 16.97,1 12,1zM7,14v4H6c-0.55,0 -1,-0.45 -1,-1v-3H7zM19,18h-2v-4h2V18z" /> \ No newline at end of file diff --git a/core/res/res/drawable/ic_bt_pointing_hid.xml b/core/res/res/drawable/ic_bt_pointing_hid.xml index de97e249789f..470d1528b4fb 100644 --- a/core/res/res/drawable/ic_bt_pointing_hid.xml +++ b/core/res/res/drawable/ic_bt_pointing_hid.xml @@ -21,6 +21,5 @@ android:tint="?android:attr/colorControlNormal"> + android:pathData="M20 9c-0.04-4.39-3.6-7.93-8-7.93S4.04 4.61 4 9v6c0 4.42 3.58 8 8 8s8-3.58 8-8V9zm-2 0h-5V3.16c2.81 0.47 4.96 2.9 5 5.84zm-7-5.84V9H6c0.04-2.94 2.19-5.37 5-5.84zM18 15c0 3.31-2.69 6-6 6s-6-2.69-6-6v-4h12v4z" /> \ No newline at end of file diff --git a/core/res/res/drawable/ic_doc_folder.xml b/core/res/res/drawable/ic_doc_folder.xml index dcbce010810e..ac29ba665609 100644 --- a/core/res/res/drawable/ic_doc_folder.xml +++ b/core/res/res/drawable/ic_doc_folder.xml @@ -20,5 +20,5 @@ Copyright (C) 2015 The Android Open Source Project android:viewportHeight="24.0"> + android:pathData="M20,18H4V8H20M20,6H12L10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6Z" /> diff --git a/core/res/res/drawable/ic_eject_24dp.xml b/core/res/res/drawable/ic_eject_24dp.xml index 321ee3b6289c..d01461aa0232 100644 --- a/core/res/res/drawable/ic_eject_24dp.xml +++ b/core/res/res/drawable/ic_eject_24dp.xml @@ -20,8 +20,5 @@ Copyright (C) 2015 The Android Open Source Project android:viewportHeight="24.0"> - + android:pathData="M5,17H19V19H5V17M12,5L5.33,15H18.67L12,5M12,8.6L14.93,13H9.07L12,8.6Z" /> diff --git a/core/res/res/drawable/ic_file_copy.xml b/core/res/res/drawable/ic_file_copy.xml index d05b55f1279f..01dff735a402 100644 --- a/core/res/res/drawable/ic_file_copy.xml +++ b/core/res/res/drawable/ic_file_copy.xml @@ -20,6 +20,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/core/res/res/drawable/ic_folder_24dp.xml b/core/res/res/drawable/ic_folder_24dp.xml index 9a386ca45e7a..b6d8a1bbf9c6 100644 --- a/core/res/res/drawable/ic_folder_24dp.xml +++ b/core/res/res/drawable/ic_folder_24dp.xml @@ -16,9 +16,9 @@ Copyright (C) 2015 The Android Open Source Project + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M20,18H4V8H20M20,6H12L10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6Z" /> diff --git a/core/res/res/drawable/ic_link.xml b/core/res/res/drawable/ic_link.xml new file mode 100644 index 000000000000..97322a4f24bd --- /dev/null +++ b/core/res/res/drawable/ic_link.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/res/res/drawable/ic_lock_lockdown.xml b/core/res/res/drawable/ic_lock_lockdown.xml index b9685d3e7cca..6c6a676a6d35 100644 --- a/core/res/res/drawable/ic_lock_lockdown.xml +++ b/core/res/res/drawable/ic_lock_lockdown.xml @@ -22,5 +22,5 @@ Copyright (C) 2018 The Android Open Source Project + android:pathData="M12,17C10.89,17 10,16.1 10,15C10,13.89 10.89,13 12,13A2,2 0 0,1 14,15A2,2 0 0,1 12,17M18,20V10H6V20H18M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10C4,8.89 4.89,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z" /> diff --git a/core/res/res/drawable/ic_lockscreen_ime.xml b/core/res/res/drawable/ic_lockscreen_ime.xml index 4b81a3c9c460..90492770c5bd 100644 --- a/core/res/res/drawable/ic_lockscreen_ime.xml +++ b/core/res/res/drawable/ic_lockscreen_ime.xml @@ -21,6 +21,5 @@ android:tint="?android:attr/colorControlNormal"> + android:pathData="M4,5A2,2 0 0,0 2,7V17A2,2 0 0,0 4,19H20A2,2 0 0,0 22,17V7A2,2 0 0,0 20,5H4M4,7H20V17H4V7M5,8V10H7V8H5M8,8V10H10V8H8M11,8V10H13V8H11M14,8V10H16V8H14M17,8V10H19V8H17M5,11V13H7V11H5M8,11V13H10V11H8M11,11V13H13V11H11M14,11V13H16V11H14M17,11V13H19V11H17M8,14V16H16V14H8Z" /> \ No newline at end of file diff --git a/core/res/res/drawable/ic_notification_alert.xml b/core/res/res/drawable/ic_notification_alert.xml index c8514acde2ac..f9bd88a9faa7 100644 --- a/core/res/res/drawable/ic_notification_alert.xml +++ b/core/res/res/drawable/ic_notification_alert.xml @@ -25,9 +25,6 @@ Copyright (C) 2016 The Android Open Source Project android:pathData="M7.1,3.6L5.7,2.2C3.3,4.0 1.7,6.8 1.5,10.0l2.0,0.0C3.7,7.3 5.0,5.0 7.1,3.6z" android:fillColor="#FFFFFFFF"/> - diff --git a/core/res/res/drawable/ic_notifications_alerted.xml b/core/res/res/drawable/ic_notifications_alerted.xml index 4bfac37e8408..6bbca37cd48c 100644 --- a/core/res/res/drawable/ic_notifications_alerted.xml +++ b/core/res/res/drawable/ic_notifications_alerted.xml @@ -19,6 +19,9 @@ Copyright (C) 2018 The Android Open Source Project android:viewportWidth="24.0" android:viewportHeight="24.0"> + diff --git a/core/res/res/drawable/ic_perm_device_info.xml b/core/res/res/drawable/ic_perm_device_info.xml index ef91c74620ac..b546992bd39d 100644 --- a/core/res/res/drawable/ic_perm_device_info.xml +++ b/core/res/res/drawable/ic_perm_device_info.xml @@ -16,9 +16,9 @@ + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7v-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7zM11,7h2v2h-2V7zM11,11h2v6h-2V11z"/> diff --git a/core/res/res/drawable/ic_phone.xml b/core/res/res/drawable/ic_phone.xml index be9b094134c8..27ada123149f 100644 --- a/core/res/res/drawable/ic_phone.xml +++ b/core/res/res/drawable/ic_phone.xml @@ -22,8 +22,5 @@ android:autoMirrored="true"> + android:pathData="M6.54 5c0.06 0.89 0.21 1.76 0.45 2.59l-1.2 1.2c-0.41-1.2-0.67-2.47-0.76-3.79h1.51m9.86 12.02c0.85 0.24 1.72 0.39 2.6 0.45 v1.49c-1.32-0.09-2.59-0.35-3.8-0.75l1.2-1.19M7.5 3H4c-0.55 0-1 0.45-1 1 0 9.39 7.61 17 17 17 0.55 0 1-0.45 1-1v-3.49c0-0.55-0.45-1-1-1-1.24 0-2.45-0.2-3.57-0.57-0.1-0.04-0.21-0.05-0.31-0.05-0.26 0-0.51 0.1 -0.71 0.29 l-2.2 2.2c-2.83-1.45-5.15-3.76-6.59-6.59l2.2-2.2c0.28-0.28 0.36 -0.67 0.25 -1.02C8.7 6.45 8.5 5.25 8.5 4c0-0.55-0.45-1-1-1z" /> \ No newline at end of file diff --git a/core/res/res/drawable/ic_print.xml b/core/res/res/drawable/ic_print.xml index 7aa251300448..b72b4d02946e 100644 --- a/core/res/res/drawable/ic_print.xml +++ b/core/res/res/drawable/ic_print.xml @@ -21,6 +21,9 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> + \ No newline at end of file diff --git a/core/res/res/drawable/ic_print_error.xml b/core/res/res/drawable/ic_print_error.xml index 37e51527e399..999e92e39e07 100644 --- a/core/res/res/drawable/ic_print_error.xml +++ b/core/res/res/drawable/ic_print_error.xml @@ -21,6 +21,6 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> \ No newline at end of file diff --git a/core/res/res/drawable/ic_qs_night_display_on.xml b/core/res/res/drawable/ic_qs_night_display_on.xml index a4755ee256e2..68004f168f2e 100644 --- a/core/res/res/drawable/ic_qs_night_display_on.xml +++ b/core/res/res/drawable/ic_qs_night_display_on.xml @@ -21,6 +21,6 @@ + android:pathData="M17.75,4.09L15.22,6.03L16.13,9.09L13.5,7.28L10.87,9.09L11.78,6.03L9.25,4.09L12.44,4L13.5,1L14.56,4L17.75,4.09M21.25,11L19.61,12.25L20.2,14.23L18.5,13.06L16.8,14.23L17.39,12.25L15.75,11L17.81,10.95L18.5,9L19.19,10.95L21.25,11M18.97,15.95C19.8,15.87 20.69,17.05 20.16,17.8C19.84,18.25 19.5,18.67 19.08,19.07C15.17,23 8.84,23 4.94,19.07C1.03,15.17 1.03,8.83 4.94,4.93C5.34,4.53 5.76,4.17 6.21,3.85C6.96,3.32 8.14,4.21 8.06,5.04C7.79,7.9 8.75,10.87 10.95,13.06C13.14,15.26 16.1,16.22 18.97,15.95M17.33,17.97C14.5,17.81 11.7,16.64 9.53,14.5C7.36,12.31 6.2,9.5 6.04,6.68C3.23,9.82 3.34,14.64 6.35,17.66C9.37,20.67 14.19,20.78 17.33,17.97Z" /> diff --git a/core/res/res/drawable/ic_sd_card_48dp.xml b/core/res/res/drawable/ic_sd_card_48dp.xml index 10fd12054820..d0729fe39533 100644 --- a/core/res/res/drawable/ic_sd_card_48dp.xml +++ b/core/res/res/drawable/ic_sd_card_48dp.xml @@ -16,8 +16,8 @@ Copyright (C) 2015 The Android Open Source Project + android:viewportWidth="24.0" + android:viewportHeight="24.0"> diff --git a/core/res/res/drawable/ic_settings_print.xml b/core/res/res/drawable/ic_settings_print.xml index 68b627cf4dc9..b77e6ba0f2d8 100644 --- a/core/res/res/drawable/ic_settings_print.xml +++ b/core/res/res/drawable/ic_settings_print.xml @@ -21,5 +21,8 @@ android:tint="?android:attr/colorControlNormal"> + android:pathData="M19 8h-1V3H6v5H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zM8 5h8v3H8V5zm8 12v2H8v-4h8v2zm2-2v-2H6v2H4v-4c0-0.55 0.45 -1 1-1h14c0.55 0 1 0.45 1 1v4h-2z" /> + diff --git a/core/res/res/drawable/ic_voice_search_api_material.xml b/core/res/res/drawable/ic_voice_search_api_material.xml index a02621820b62..5aa5b56faa2d 100644 --- a/core/res/res/drawable/ic_voice_search_api_material.xml +++ b/core/res/res/drawable/ic_voice_search_api_material.xml @@ -20,6 +20,9 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24.0" android:tint="?attr/colorControlNormal"> + diff --git a/core/res/res/drawable/perm_group_call_log.xml b/core/res/res/drawable/perm_group_call_log.xml index a37ed88bebfc..e60770f7b160 100644 --- a/core/res/res/drawable/perm_group_call_log.xml +++ b/core/res/res/drawable/perm_group_call_log.xml @@ -23,7 +23,7 @@ android:viewportHeight="24.0"> + android:pathData="M6.54 5c0.06 0.89 0.21 1.76 0.45 2.59l-1.2 1.2c-0.41-1.2-0.67-2.47-0.76-3.79h1.51m9.86 12.02c0.85 0.24 1.72 0.39 2.6 0.45 v1.49c-1.32-0.09-2.59-0.35-3.8-0.75l1.2-1.19M7.5 3H4c-0.55 0-1 0.45-1 1 0 9.39 7.61 17 17 17 0.55 0 1-0.45 1-1v-3.49c0-0.55-0.45-1-1-1-1.24 0-2.45-0.2-3.57-0.57-0.1-0.04-0.21-0.05-0.31-0.05-0.26 0-0.51 0.1 -0.71 0.29 l-2.2 2.2c-2.83-1.45-5.15-3.76-6.59-6.59l2.2-2.2c0.28-0.28 0.36 -0.67 0.25 -1.02C8.7 6.45 8.5 5.25 8.5 4c0-0.55-0.45-1-1-1z" /> diff --git a/core/res/res/drawable/perm_group_location.xml b/core/res/res/drawable/perm_group_location.xml index a87fc0dc43df..633610ae55f9 100644 --- a/core/res/res/drawable/perm_group_location.xml +++ b/core/res/res/drawable/perm_group_location.xml @@ -15,16 +15,16 @@ limitations under the License. --> + android:pathData="M 10 2 C 6.13 2 3 5.13 3 9 c 0 5.25 7 13 7 13 s 7 -7.75 7 -13 C 17 5.13 13.87 2 10 2 z M 5 9 c 0 -2.76 2.24 -5 5 -5 s 5 2.24 5 5 c 0 2.88 -2.88 7.19 -5 9.88 C 7.92 16.21 5 11.85 5 9 z"/> + android:pathData="M 10 9 m -2.5 0 a 2.5 2.5 0 1 1 5 0 a 2.5 2.5 0 1 1 -5 0"/> diff --git a/core/res/res/drawable/perm_group_phone_calls.xml b/core/res/res/drawable/perm_group_phone_calls.xml index 563222698b46..ff4c138013b1 100644 --- a/core/res/res/drawable/perm_group_phone_calls.xml +++ b/core/res/res/drawable/perm_group_phone_calls.xml @@ -22,8 +22,5 @@ android:viewportHeight="24"> + android:pathData="M6.54 5c0.06 0.89 0.21 1.76 0.45 2.59l-1.2 1.2c-0.41-1.2-0.67-2.47-0.76-3.79h1.51m9.86 12.02c0.85 0.24 1.72 0.39 2.6 0.45 v1.49c-1.32-0.09-2.59-0.35-3.8-0.75l1.2-1.19M7.5 3H4c-0.55 0-1 0.45-1 1 0 9.39 7.61 17 17 17 0.55 0 1-0.45 1-1v-3.49c0-0.55-0.45-1-1-1-1.24 0-2.45-0.2-3.57-0.57-0.1-0.04-0.21-0.05-0.31-0.05-0.26 0-0.51 0.1 -0.71 0.29 l-2.2 2.2c-2.83-1.45-5.15-3.76-6.59-6.59l2.2-2.2c0.28-0.28 0.36 -0.67 0.25 -1.02C8.7 6.45 8.5 5.25 8.5 4c0-0.55-0.45-1-1-1z" /> diff --git a/core/res/res/drawable/stat_notify_missed_call.xml b/core/res/res/drawable/stat_notify_missed_call.xml new file mode 100644 index 000000000000..960ee7844e95 --- /dev/null +++ b/core/res/res/drawable/stat_notify_missed_call.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/core/res/res/drawable/stat_sys_location.xml b/core/res/res/drawable/stat_sys_location.xml new file mode 100644 index 000000000000..9bb7baee8d91 --- /dev/null +++ b/core/res/res/drawable/stat_sys_location.xml @@ -0,0 +1,5 @@ + + diff --git a/core/res/res/layout/accessibility_button_chooser_item.xml b/core/res/res/layout/accessibility_button_chooser_item.xml index 33d6fa2862f7..70905ca19192 100644 --- a/core/res/res/layout/accessibility_button_chooser_item.xml +++ b/core/res/res/layout/accessibility_button_chooser_item.xml @@ -45,7 +45,7 @@ android:textAppearance="?attr/textAppearanceSmall" android:textColor="?attr/textColorPrimary" android:textSize="12sp" - android:fontFamily="sans-serif-condensed" + android:fontFamily="@*android:string/config_bodyFontFamily" android:gravity="top|center_horizontal" android:minLines="2" android:maxLines="2" diff --git a/core/res/res/layout/accessibility_enable_service_warning.xml b/core/res/res/layout/accessibility_enable_service_warning.xml index 01ef10177c5a..fc6f49837519 100644 --- a/core/res/res/layout/accessibility_enable_service_warning.xml +++ b/core/res/res/layout/accessibility_enable_service_warning.xml @@ -51,7 +51,7 @@ android:gravity="center" android:textSize="20sp" android:textColor="?android:attr/textColorPrimary" - android:fontFamily="google-sans-medium"/> + android:fontFamily="@*android:string/config_headlineFontFamily"/> + android:fontFamily="@*android:string/config_bodyFontFamily"/> + android:fontFamily="@*android:string/config_headlineFontFamily"/> + android:fontFamily="@*android:string/config_bodyFontFamily"/> + android:fontFamily="@*android:string/config_headlineFontFamily"/> + android:fontFamily="@*android:string/config_bodyFontFamily" /> + android:fontFamily="@*android:string/config_bodyFontFamily"/> + android:fontFamily="@*android:string/config_bodyFontFamily"/> diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml index 178505c264a4..b1510fdcb93d 100644 --- a/core/res/res/layout/alert_dialog_material.xml +++ b/core/res/res/layout/alert_dialog_material.xml @@ -54,7 +54,7 @@ android:layout_height="wrap_content" android:paddingEnd="?attr/dialogPreferredPadding" android:paddingStart="?attr/dialogPreferredPadding" - style="@style/TextAppearance.Material.Subhead" /> + style="@style/TextAppearance.DeviceDefault.Subhead" /> +