1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.server.wm.app; 18 19 import static android.server.wm.app.Components.TestActivity.COMMAND_NAVIGATE_UP_TO; 20 import static android.server.wm.app.Components.TestActivity.COMMAND_START_ACTIVITIES; 21 import static android.server.wm.app.Components.TestActivity.COMMAND_START_ACTIVITY; 22 import static android.server.wm.app.Components.TestActivity.EXTRA_CONFIG_ASSETS_SEQ; 23 import static android.server.wm.app.Components.TestActivity.EXTRA_FIXED_ORIENTATION; 24 import static android.server.wm.app.Components.TestActivity.EXTRA_INTENT; 25 import static android.server.wm.app.Components.TestActivity.EXTRA_INTENTS; 26 import static android.server.wm.app.Components.TestActivity.EXTRA_NO_IDLE; 27 import static android.server.wm.app.Components.TestActivity.EXTRA_OPTION; 28 import static android.server.wm.app.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF; 29 30 import android.content.BroadcastReceiver; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.content.res.Configuration; 35 import android.os.Bundle; 36 import android.os.Looper; 37 import android.os.Parcelable; 38 import android.util.Log; 39 import android.view.animation.Animation; 40 import android.view.animation.RotateAnimation; 41 import android.widget.ProgressBar; 42 43 import java.util.Arrays; 44 45 public class TestActivity extends AbstractLifecycleLogActivity { 46 47 private BroadcastReceiver mReceiver = new BroadcastReceiver() { 48 @Override 49 public void onReceive(Context context, Intent intent) { 50 if (intent != null && TEST_ACTIVITY_ACTION_FINISH_SELF.equals(intent.getAction())) { 51 finish(); 52 } 53 } 54 }; 55 56 @Override onCreate(Bundle icicle)57 protected void onCreate(Bundle icicle) { 58 super.onCreate(icicle); 59 60 // Set the fixed orientation if requested 61 if (getIntent().hasExtra(EXTRA_FIXED_ORIENTATION)) { 62 final int ori = Integer.parseInt(getIntent().getStringExtra(EXTRA_FIXED_ORIENTATION)); 63 setRequestedOrientation(ori); 64 } 65 66 if (getIntent().hasExtra(EXTRA_NO_IDLE)) { 67 preventActivityIdle(); 68 } 69 } 70 71 /** Starts a repeated animation on main thread to make its message queue non-empty. */ preventActivityIdle()72 private void preventActivityIdle() { 73 final ProgressBar progressBar = new ProgressBar(this); 74 progressBar.setIndeterminate(true); 75 setContentView(progressBar); 76 final RotateAnimation animation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 77 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); 78 animation.setRepeatCount(Animation.INFINITE); 79 progressBar.startAnimation(animation); 80 81 Looper.myLooper().getQueue().addIdleHandler(() -> { 82 if (progressBar.isAnimating()) { 83 throw new RuntimeException("Shouldn't receive idle while animating"); 84 } 85 return false; 86 }); 87 } 88 89 @Override onStart()90 protected void onStart() { 91 super.onStart(); 92 registerReceiver(mReceiver, new IntentFilter(TEST_ACTIVITY_ACTION_FINISH_SELF), 93 Context.RECEIVER_EXPORTED); 94 } 95 96 @Override onResume()97 protected void onResume() { 98 super.onResume(); 99 final Configuration configuration = getResources().getConfiguration(); 100 dumpConfiguration(configuration); 101 dumpAssetSeqNumber(configuration); 102 dumpConfigInfo(); 103 } 104 105 @Override onStop()106 protected void onStop() { 107 super.onStop(); 108 unregisterReceiver(mReceiver); 109 } 110 111 @Override handleCommand(String command, Bundle data)112 public void handleCommand(String command, Bundle data) { 113 final Bundle options = data.getParcelable(EXTRA_OPTION); 114 switch (command) { 115 case COMMAND_START_ACTIVITY: 116 final Intent startIntent = data.getParcelable(EXTRA_INTENT); 117 try { 118 startActivity(startIntent, options); 119 } catch (Exception e) { 120 Log.w(getTag(), "Failed to startActivity: " + startIntent, e); 121 } 122 break; 123 case COMMAND_START_ACTIVITIES: 124 final Parcelable[] intents = data.getParcelableArray(EXTRA_INTENTS); 125 startActivities(Arrays.copyOf(intents, intents.length, Intent[].class), options); 126 break; 127 case COMMAND_NAVIGATE_UP_TO: 128 final Intent intent = data.getParcelable(EXTRA_INTENT); 129 try { 130 navigateUpTo(intent); 131 } catch (Exception e) { 132 // Expected if the target activity in not exported with different uid. 133 Log.w(getTag(), "Failed to navigateUpTo: " + intent, e); 134 } 135 break; 136 default: 137 super.handleCommand(command, data); 138 } 139 } 140 141 @Override onConfigurationChanged(Configuration newConfig)142 public void onConfigurationChanged(Configuration newConfig) { 143 super.onConfigurationChanged(newConfig); 144 dumpConfiguration(newConfig); 145 dumpAssetSeqNumber(newConfig); 146 dumpConfigInfo(); 147 } 148 149 @Override onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig)150 public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) { 151 super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig); 152 dumpConfiguration(newConfig); 153 dumpAssetSeqNumber(newConfig); 154 dumpConfigInfo(); 155 } 156 dumpAssetSeqNumber(Configuration newConfig)157 private void dumpAssetSeqNumber(Configuration newConfig) { 158 withTestJournalClient(client -> { 159 final Bundle extras = new Bundle(); 160 extras.putInt(EXTRA_CONFIG_ASSETS_SEQ, newConfig.assetsSeq); 161 client.putExtras(extras); 162 }); 163 } 164 } 165